mirror of
https://github.com/redstrate/Kawari.git
synced 2025-06-08 17:37:46 +00:00
Add world server, fix reading compression type
This doesn't work yet as we don't implement Oodle decompression, but we at least start recieving the packets.
This commit is contained in:
parent
1cd68ee1a3
commit
e5d143d2c6
5 changed files with 68 additions and 10 deletions
1
run.sh
1
run.sh
|
@ -8,4 +8,5 @@ cargo run -q --package kawari --bin kawari-login &
|
||||||
cargo run -q --package kawari --bin kawari-patch &
|
cargo run -q --package kawari --bin kawari-patch &
|
||||||
cargo run -q --package kawari --bin kawari-web &
|
cargo run -q --package kawari --bin kawari-web &
|
||||||
cargo run -q --package kawari --bin kawari-lobby &
|
cargo run -q --package kawari --bin kawari-lobby &
|
||||||
|
cargo run -q --package kawari --bin kawari-world &
|
||||||
wait
|
wait
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::fs::read;
|
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
use kawari::client_select_data::{ClientCustomizeData, ClientSelectData};
|
use kawari::client_select_data::{ClientCustomizeData, ClientSelectData};
|
||||||
|
@ -23,7 +22,10 @@ async fn main() {
|
||||||
let (socket, _) = listener.accept().await.unwrap();
|
let (socket, _) = listener.accept().await.unwrap();
|
||||||
let (mut read, mut write) = tokio::io::split(socket);
|
let (mut read, mut write) = tokio::io::split(socket);
|
||||||
|
|
||||||
let mut state = State {client_key:None, session_id: None };
|
let mut state = State {
|
||||||
|
client_key: None,
|
||||||
|
session_id: None,
|
||||||
|
};
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut buf = [0; 2056];
|
let mut buf = [0; 2056];
|
||||||
|
@ -77,7 +79,8 @@ async fn main() {
|
||||||
} => {
|
} => {
|
||||||
tracing::info!("Client is joining the world...");
|
tracing::info!("Client is joining the world...");
|
||||||
|
|
||||||
send_enter_world(&mut write, &state, *sequence, *lookup_id).await;
|
send_enter_world(&mut write, &state, *sequence, *lookup_id)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("The server is recieving a IPC response packet!")
|
panic!("The server is recieving a IPC response packet!")
|
||||||
|
@ -131,7 +134,7 @@ async fn send_account_list(socket: &mut WriteHalf<TcpStream>, state: &State) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// send the client the service account list
|
// send the client the service account list
|
||||||
let mut service_accounts = [ServiceAccount {
|
let service_accounts = [ServiceAccount {
|
||||||
id: 0x002E4A2B,
|
id: 0x002E4A2B,
|
||||||
unk1: 0,
|
unk1: 0,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
|
46
src/bin/kawari-world.rs
Normal file
46
src/bin/kawari-world.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
use kawari::packet::{SegmentType, State, parse_packet, send_keep_alive};
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
let listener = TcpListener::bind("127.0.0.1:7100").await.unwrap();
|
||||||
|
|
||||||
|
tracing::info!("World server started on 7100");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (socket, _) = listener.accept().await.unwrap();
|
||||||
|
let (mut read, mut write) = tokio::io::split(socket);
|
||||||
|
|
||||||
|
let mut state = State {
|
||||||
|
client_key: None,
|
||||||
|
session_id: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut buf = [0; 2056];
|
||||||
|
loop {
|
||||||
|
let n = read.read(&mut buf).await.expect("Failed to read data!");
|
||||||
|
|
||||||
|
if n != 0 {
|
||||||
|
let segments = parse_packet(&buf[..n], &mut state).await;
|
||||||
|
for segment in &segments {
|
||||||
|
match &segment.segment_type {
|
||||||
|
SegmentType::Ipc { data } => {
|
||||||
|
panic!("The server is recieving a IPC response or unknown packet!")
|
||||||
|
}
|
||||||
|
SegmentType::KeepAlive { id, timestamp } => {
|
||||||
|
send_keep_alive(&mut write, &state, *id, *timestamp).await
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("The server is recieving a response or unknown packet!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,7 +49,7 @@ where
|
||||||
let decryption_result = blowfish_decode(encryption_key.as_ptr(), 16, data.as_ptr(), size);
|
let decryption_result = blowfish_decode(encryption_key.as_ptr(), 16, data.as_ptr(), size);
|
||||||
let decrypted_data = slice::from_raw_parts(decryption_result, size as usize);
|
let decrypted_data = slice::from_raw_parts(decryption_result, size as usize);
|
||||||
|
|
||||||
write("decrypted.bin", &decrypted_data).unwrap();
|
write("decrypted.bin", decrypted_data).unwrap();
|
||||||
|
|
||||||
let mut cursor = Cursor::new(&decrypted_data);
|
let mut cursor = Cursor::new(&decrypted_data);
|
||||||
T::read_options(&mut cursor, endian, ())
|
T::read_options(&mut cursor, endian, ())
|
||||||
|
|
|
@ -11,7 +11,7 @@ use tokio::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{read_bool_from, read_string, write_bool_as},
|
common::read_string,
|
||||||
encryption::{decrypt, encrypt},
|
encryption::{decrypt, encrypt},
|
||||||
ipc::IPCSegment,
|
ipc::IPCSegment,
|
||||||
};
|
};
|
||||||
|
@ -61,6 +61,15 @@ pub enum SegmentType {
|
||||||
KeepAliveResponse { id: u32, timestamp: u32 },
|
KeepAliveResponse { id: u32, timestamp: u32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[binrw]
|
||||||
|
#[brw(repr = u8)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum CompressionType {
|
||||||
|
Uncompressed = 0,
|
||||||
|
ZLib = 1,
|
||||||
|
Oodle = 2,
|
||||||
|
}
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct PacketHeader {
|
struct PacketHeader {
|
||||||
|
@ -71,9 +80,7 @@ struct PacketHeader {
|
||||||
connection_type: ConnectionType,
|
connection_type: ConnectionType,
|
||||||
segment_count: u16,
|
segment_count: u16,
|
||||||
unk3: u8,
|
unk3: u8,
|
||||||
#[br(map = read_bool_from::<u8>)]
|
compressed: CompressionType,
|
||||||
#[bw(map = write_bool_as::<u8>)]
|
|
||||||
compressed: bool,
|
|
||||||
unk4: u16,
|
unk4: u16,
|
||||||
unk5: u32, // iolite says the size after oodle decompression
|
unk5: u32, // iolite says the size after oodle decompression
|
||||||
}
|
}
|
||||||
|
@ -108,6 +115,7 @@ impl PacketSegment {
|
||||||
#[brw(import(encryption_key: Option<&[u8]>))]
|
#[brw(import(encryption_key: Option<&[u8]>))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Packet {
|
struct Packet {
|
||||||
|
#[br(dbg)]
|
||||||
header: PacketHeader,
|
header: PacketHeader,
|
||||||
#[br(count = header.segment_count, args { inner: (encryption_key,) })]
|
#[br(count = header.segment_count, args { inner: (encryption_key,) })]
|
||||||
#[bw(args(encryption_key))]
|
#[bw(args(encryption_key))]
|
||||||
|
@ -144,7 +152,7 @@ pub async fn send_packet(
|
||||||
connection_type: ConnectionType::Lobby,
|
connection_type: ConnectionType::Lobby,
|
||||||
segment_count: segments.len() as u16,
|
segment_count: segments.len() as u16,
|
||||||
unk3: 0,
|
unk3: 0,
|
||||||
compressed: false,
|
compressed: CompressionType::Uncompressed,
|
||||||
unk4: 0,
|
unk4: 0,
|
||||||
unk5: 0,
|
unk5: 0,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue