mirror of
https://github.com/RustySamovar/RustySamovar.git
synced 2024-11-23 11:06:02 +00:00
Code cleanup
This commit is contained in:
parent
f312e61323
commit
c0eedc4a67
@ -17,6 +17,8 @@ packet-processor-macro = { path = "../packet-processor-macro" }
|
|||||||
packet-processor = { path = "../packet-processor" }
|
packet-processor = { path = "../packet-processor" }
|
||||||
rs-ipc = { path = "../rs-ipc" }
|
rs-ipc = { path = "../rs-ipc" }
|
||||||
excel-hash-wrapper-macro = { path = "../excel-hash-wrapper-macro" }
|
excel-hash-wrapper-macro = { path = "../excel-hash-wrapper-macro" }
|
||||||
|
rs-nodeconf = { path = "../rs-nodeconf" }
|
||||||
|
rs-utils = { path = "../rs-utils" }
|
||||||
|
|
||||||
prost = "0.8"
|
prost = "0.8"
|
||||||
bytes = "1.1.0"
|
bytes = "1.1.0"
|
||||||
|
@ -12,7 +12,6 @@ use crate::collection;
|
|||||||
use sea_orm::{entity::*, error::*, query::*, DbConn, FromQueryResult, Database};
|
use sea_orm::{entity::*, error::*, query::*, DbConn, FromQueryResult, Database};
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use crate::JsonManager;
|
use crate::JsonManager;
|
||||||
use crate::server::AuthManager;
|
|
||||||
use crate::utils::IdManager;
|
use crate::utils::IdManager;
|
||||||
|
|
||||||
pub use super::player_info::Model as PlayerInfo;
|
pub use super::player_info::Model as PlayerInfo;
|
||||||
|
@ -15,10 +15,11 @@ use packet_processor_macro::*;
|
|||||||
use packet_processor::*;
|
use packet_processor::*;
|
||||||
use serde_json::de::Read;
|
use serde_json::de::Read;
|
||||||
use crate::{DatabaseManager, JsonManager, LuaManager};
|
use crate::{DatabaseManager, JsonManager, LuaManager};
|
||||||
use crate::utils::{IdManager, TimeManager};
|
use crate::utils::{IdManager};
|
||||||
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
use crate::luamanager::Vector;
|
use crate::luamanager::Vector;
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
use super::entities::Entity;
|
use super::entities::Entity;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -2,7 +2,7 @@ use chrono::NaiveDateTime;
|
|||||||
|
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
use crate::utils::TimeManager;
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
#[serde(rename_all="PascalCase")]
|
#[serde(rename_all="PascalCase")]
|
||||||
|
@ -7,7 +7,7 @@ extern crate num_derive;
|
|||||||
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
mod node;
|
use rs_nodeconf::NodeConfig;
|
||||||
|
|
||||||
mod server;
|
mod server;
|
||||||
mod utils;
|
mod utils;
|
||||||
@ -18,12 +18,12 @@ mod entitymanager;
|
|||||||
|
|
||||||
mod subsystems;
|
mod subsystems;
|
||||||
|
|
||||||
use server::NetworkServer;
|
|
||||||
use dbmanager::DatabaseManager;
|
use dbmanager::DatabaseManager;
|
||||||
use jsonmanager::JsonManager;
|
use jsonmanager::JsonManager;
|
||||||
use luamanager::LuaManager;
|
use luamanager::LuaManager;
|
||||||
use subsystems::EntitySubsystem;
|
use subsystems::EntitySubsystem;
|
||||||
use entitymanager::EntityManager;
|
use entitymanager::EntityManager;
|
||||||
|
use crate::server::GameServer;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
//pretty_env_logger::init();
|
//pretty_env_logger::init();
|
||||||
@ -35,6 +35,8 @@ fn main() {
|
|||||||
.with_test_writer()
|
.with_test_writer()
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let mut ns = NetworkServer::new("0.0.0.0", 4242).unwrap();
|
let nc = NodeConfig::new();
|
||||||
ns.run().expect("Failed to serve!");
|
let mut gs = GameServer::new(&nc);
|
||||||
|
|
||||||
|
gs.run();
|
||||||
}
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
use rs_ipc::{PubSocket, PullSocket, PushSocket, Result, SubSocket};
|
|
||||||
|
|
||||||
pub struct NodeConfig {
|
|
||||||
pub in_queue_addr: String,
|
|
||||||
pub in_queue_port: u16,
|
|
||||||
pub out_queue_addr: String,
|
|
||||||
pub out_queue_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NodeConfig {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
NodeConfig {
|
|
||||||
in_queue_addr: "127.0.0.1".to_string(),
|
|
||||||
in_queue_port: 9012,
|
|
||||||
out_queue_addr: "127.0.0.1".to_string(),
|
|
||||||
out_queue_port: 9014,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bind_in_queue(&self) -> Result<PubSocket> {
|
|
||||||
PubSocket::bind_tcp(&self.in_queue_addr, self.in_queue_port)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bind_out_queue(&self) -> Result<PullSocket> {
|
|
||||||
PullSocket::bind_tcp(&self.out_queue_addr, self.out_queue_port)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn connect_in_queue(&self) -> Result<SubSocket> {
|
|
||||||
SubSocket::connect_tcp(&self.in_queue_addr, self.in_queue_port)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn connect_out_queue(&self) -> Result<PushSocket> {
|
|
||||||
PushSocket::connect_tcp(&self.out_queue_addr, self.out_queue_port)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
mod config;
|
|
||||||
|
|
||||||
pub use config::NodeConfig;
|
|
@ -1,137 +0,0 @@
|
|||||||
use openssl::hash::MessageDigest;
|
|
||||||
use openssl::pkey::PKey;
|
|
||||||
use openssl::rsa::Padding;
|
|
||||||
use openssl::sign::Signer;
|
|
||||||
use std::sync::mpsc;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
use prost::Message;
|
|
||||||
|
|
||||||
use rs_ipc::{IpcMessage, PushSocket};
|
|
||||||
|
|
||||||
use packet_processor_macro::*;
|
|
||||||
#[macro_use]
|
|
||||||
use packet_processor::*;
|
|
||||||
use crate::node::NodeConfig;
|
|
||||||
|
|
||||||
#[packet_processor(GetPlayerTokenReq)]
|
|
||||||
pub struct AuthManager {
|
|
||||||
conv_to_user: HashMap<u32, u32>,
|
|
||||||
user_to_conv: HashMap<u32, u32>,
|
|
||||||
//packets_to_send_tx: mpsc::Sender<IpcMessage>,
|
|
||||||
packets_to_send_tx: PushSocket,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthManager {
|
|
||||||
pub const SPOOFED_PLAYER_UID: u32 = 1337;
|
|
||||||
|
|
||||||
pub fn new(node_config: &NodeConfig) -> AuthManager {
|
|
||||||
let mut am = AuthManager {
|
|
||||||
conv_to_user: HashMap::new(),
|
|
||||||
user_to_conv: HashMap::new(),
|
|
||||||
packet_callbacks: HashMap::new(),
|
|
||||||
packets_to_send_tx: node_config.connect_out_queue().unwrap(),
|
|
||||||
};
|
|
||||||
|
|
||||||
am.register();
|
|
||||||
|
|
||||||
return am;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn process_get_player_token(&mut self, conv: u32, metadata: &proto::PacketHead, req: &proto::GetPlayerTokenReq, rsp: &mut proto::GetPlayerTokenRsp) {
|
|
||||||
let seed: u64 = 0xBABECAFEF00D; // TODO: use real value!
|
|
||||||
let client_hardcoded_seed: u64 = 0x12345678;
|
|
||||||
let uid = self.get_uid_by_account_id(req.account_uid.parse().unwrap());
|
|
||||||
|
|
||||||
rsp.account_type = req.account_type;
|
|
||||||
rsp.account_uid = req.account_uid.clone();
|
|
||||||
rsp.token = req.account_token.clone();
|
|
||||||
rsp.secret_key_seed = seed; // TODO: temporary workaround!
|
|
||||||
rsp.uid = uid;
|
|
||||||
|
|
||||||
if req.key_id > 0 { // TODO: detect client version properly!
|
|
||||||
// Versions 2.7.5x+ use different algorithm for key initialization
|
|
||||||
|
|
||||||
// TODO: as of now (2022-05-16) this algorithm here is more of a PoC, because we can't really sign the data
|
|
||||||
// or decrypt the client seed we're getting from the client.
|
|
||||||
//
|
|
||||||
// Connecting to our server still requires patching the client to disable signature verification and hardcoding
|
|
||||||
// some known client seed value. This will allow the patched client to connect to official servers (beware of
|
|
||||||
// the ban for modding the client!)
|
|
||||||
//
|
|
||||||
// An alternative approach to hardcoding the client seed would be to employ RCE in WindSeedClientNotify to extract
|
|
||||||
// the seed from the client itself. That still would require patching the client though (to allow invalid signatures),
|
|
||||||
// so it's of a very little difference to us.
|
|
||||||
//
|
|
||||||
// Another alternative is to replace keys inside global-metadata.dat file, but that requires writing an encryption
|
|
||||||
// tool. While still possible, it's tiresome, and won't allow patched client to connect to official server without
|
|
||||||
// switching back and forth between two versions of global-metadata.dat file.
|
|
||||||
|
|
||||||
let key_id = req.key_id as u8;
|
|
||||||
|
|
||||||
let rsa_key_collection = mhycrypt::load_rsa_keys("RSAConfig", "keys");
|
|
||||||
let keys = match rsa_key_collection.get(&key_id) {
|
|
||||||
Some(keys) => keys,
|
|
||||||
None => panic!("Unknown key ID {}!", key_id),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Decrypt received client seed
|
|
||||||
|
|
||||||
let client_seed_encrypted = base64::decode(&req.client_rand_key).unwrap();
|
|
||||||
|
|
||||||
let mut dec_buf: Vec<u8> = vec![0; 256];
|
|
||||||
|
|
||||||
let client_seed = match keys.signing_key.private_decrypt(&client_seed_encrypted, &mut dec_buf, Padding::PKCS1) {
|
|
||||||
Ok(seed_size) => {
|
|
||||||
// Note: from_be_bytes here, because client seems to swap order of bytes for the seed
|
|
||||||
u64::from_be_bytes(dec_buf[0..seed_size].try_into().unwrap())
|
|
||||||
},
|
|
||||||
Err(e) => { // TODO: must panic here!
|
|
||||||
println!("Error decrypting client seed: {}", e);
|
|
||||||
client_hardcoded_seed // TODO: temporary workaround!
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Encrypt server seed which we'll use in negotiating with the client
|
|
||||||
|
|
||||||
let mut enc_buf: Vec<u8> = vec![0; 256];
|
|
||||||
|
|
||||||
// Note: to_be_bytes here, because client seems to swap order of bytes for the seed
|
|
||||||
let seed_bytes = (seed ^ client_seed).to_be_bytes();
|
|
||||||
|
|
||||||
let len = keys.encrypt_key.public_encrypt(&seed_bytes, &mut enc_buf, Padding::PKCS1).unwrap();
|
|
||||||
|
|
||||||
// Sign it
|
|
||||||
let keypair = PKey::from_rsa(keys.signing_key.clone()).unwrap();
|
|
||||||
let mut signer = Signer::new(MessageDigest::sha256(), &keypair).unwrap();
|
|
||||||
let signature = signer.sign_oneshot_to_vec(&seed_bytes).unwrap();
|
|
||||||
|
|
||||||
rsp.key_id = key_id as u32;
|
|
||||||
rsp.server_rand_key = base64::encode(&enc_buf);
|
|
||||||
rsp.sign = base64::encode(&signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.conv_to_user.insert(conv, uid);
|
|
||||||
self.user_to_conv.insert(uid, conv);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_uid_by_account_id(&self, account_uid: u32) -> u32 {
|
|
||||||
// TODO!
|
|
||||||
return AuthManager::SPOOFED_PLAYER_UID;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_conv(&self, conv: u32) -> Option<u32> {
|
|
||||||
match self.conv_to_user.get(&conv) {
|
|
||||||
Some(uid) => return Some(*uid),
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_uid(&self, uid: u32) -> Option<u32> {
|
|
||||||
match self.user_to_conv.get(&uid) {
|
|
||||||
Some(conv) => return Some(*conv),
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
use std::io;
|
|
||||||
use std::io::Read;
|
|
||||||
use std::fs;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::net::UdpSocket;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::time::SystemTime;
|
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
use crate::utils::TimeManager;
|
|
||||||
|
|
||||||
extern crate kcp;
|
|
||||||
extern crate mhycrypt;
|
|
||||||
|
|
||||||
use kcp::Kcp;
|
|
||||||
|
|
||||||
pub struct ClientConnection {
|
|
||||||
conv: u32,
|
|
||||||
token: u32,
|
|
||||||
ikcp: Kcp<Source>,
|
|
||||||
established_time: SystemTime,
|
|
||||||
key: [u8; 0x1000],
|
|
||||||
pending_seed: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Source
|
|
||||||
{
|
|
||||||
address: Option<SocketAddr>,
|
|
||||||
socket: UdpSocket,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Write for Source {
|
|
||||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
|
||||||
return self.socket.send_to(data, self.address.expect("Unknown destination address!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientConnection {
|
|
||||||
pub fn new(socket: UdpSocket, conv: u32, token: u32) -> ClientConnection {
|
|
||||||
let s = Source {
|
|
||||||
address: None,
|
|
||||||
socket: socket,
|
|
||||||
};
|
|
||||||
|
|
||||||
return ClientConnection {
|
|
||||||
conv: conv,
|
|
||||||
token: token,
|
|
||||||
ikcp: Kcp::new(conv, token, s),
|
|
||||||
established_time: SystemTime::now(),
|
|
||||||
key: ClientConnection::read_key("master").try_into().expect("Incorrect master key"),
|
|
||||||
pending_seed: None,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_source(&mut self, new_source: SocketAddr) {
|
|
||||||
self.ikcp.output.0.address = Some(new_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn process_udp_packet(&mut self, data: &[u8]) -> Vec<Vec<u8>> {
|
|
||||||
match self.pending_seed {
|
|
||||||
None => {},
|
|
||||||
Some(seed) => {
|
|
||||||
mhycrypt::mhy_generate_key(&mut self.key, seed, false);
|
|
||||||
self.pending_seed = None;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut packets: Vec<Vec<u8>> = Vec::new();
|
|
||||||
self.ikcp.input(data).unwrap();
|
|
||||||
self.ikcp.update(self.elapsed_time_millis()).unwrap();
|
|
||||||
self.ikcp.flush().unwrap();
|
|
||||||
loop {
|
|
||||||
let mut buf = [0u8; 0x20000];
|
|
||||||
match self.ikcp.recv(&mut buf) {
|
|
||||||
Err(_) => break,
|
|
||||||
Ok(size) => {
|
|
||||||
#[cfg(feature = "raw_packet_dump")]
|
|
||||||
{
|
|
||||||
use pretty_hex::*;
|
|
||||||
let cfg = HexConfig {title: true, width: 16, group: 0, ascii: true, ..HexConfig::default() };
|
|
||||||
println!("{:?}", buf[..size].to_vec().hex_conf(cfg));
|
|
||||||
}
|
|
||||||
mhycrypt::mhy_xor(&mut buf[..size], &self.key);
|
|
||||||
let data = buf[..size].to_owned();
|
|
||||||
packets.push(data);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.ikcp.update(self.elapsed_time_millis()).unwrap();
|
|
||||||
return packets;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_key(&mut self, seed: u64) {
|
|
||||||
self.pending_seed = Some(seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_key(key_name: &str) -> Vec<u8> {
|
|
||||||
let filename = format!("./{}/{}.key", "keys", key_name);
|
|
||||||
let mut f = fs::File::open(&filename).expect(&format!("File '{}' not found", filename));
|
|
||||||
let metadata = fs::metadata(&filename).expect("unable to read metadata");
|
|
||||||
let mut buffer = vec![0; metadata.len() as usize];
|
|
||||||
f.read(&mut buffer).expect("buffer overflow");
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn elapsed_time_millis(&self) -> u32 {
|
|
||||||
return TimeManager::duration_since(self.established_time).try_into().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_udp_packet(&mut self, data: &[u8]) {
|
|
||||||
let mut buf = data.to_owned();
|
|
||||||
mhycrypt::mhy_xor(&mut buf, &self.key);
|
|
||||||
self.ikcp.send(&buf).expect("Failed to send data!");
|
|
||||||
self.ikcp.flush().unwrap();
|
|
||||||
self.ikcp.update(self.elapsed_time_millis()).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,7 +14,7 @@ use crate::LuaManager;
|
|||||||
use crate::server::LoginManager;
|
use crate::server::LoginManager;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use crate::entitymanager::EntityManager;
|
use crate::entitymanager::EntityManager;
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
use crate::subsystems::{InventorySubsystem, NpcSubsystem, ShopSubsystem};
|
use crate::subsystems::{InventorySubsystem, NpcSubsystem, ShopSubsystem};
|
||||||
use crate::subsystems::misc::{PauseSubsystem, SceneSubsystem, SocialSubsystem, TeleportSubsystem};
|
use crate::subsystems::misc::{PauseSubsystem, SceneSubsystem, SocialSubsystem, TeleportSubsystem};
|
||||||
|
|
||||||
|
@ -13,11 +13,11 @@ use crate::{DatabaseManager, luamanager};
|
|||||||
use crate::JsonManager;
|
use crate::JsonManager;
|
||||||
|
|
||||||
use crate::utils::{AvatarBuilder, IdManager, Remapper};
|
use crate::utils::{AvatarBuilder, IdManager, Remapper};
|
||||||
use crate::utils::TimeManager;
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
use crate::dbmanager::database_manager::AvatarInfo as DbAvatarInfo;
|
use crate::dbmanager::database_manager::AvatarInfo as DbAvatarInfo;
|
||||||
use crate::entitymanager::EntityManager;
|
use crate::entitymanager::EntityManager;
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
|
|
||||||
#[packet_processor(PlayerLoginReq)]
|
#[packet_processor(PlayerLoginReq)]
|
||||||
pub struct LoginManager {
|
pub struct LoginManager {
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
mod network_server;
|
|
||||||
mod game_server;
|
mod game_server;
|
||||||
mod game_world;
|
mod game_world;
|
||||||
mod auth_manager;
|
|
||||||
mod login_manager;
|
mod login_manager;
|
||||||
mod client_connection;
|
|
||||||
|
|
||||||
pub use self::network_server::NetworkServer;
|
|
||||||
pub use self::game_server::GameServer;
|
pub use self::game_server::GameServer;
|
||||||
pub use self::game_world::GameWorld;
|
pub use self::game_world::GameWorld;
|
||||||
pub use self::auth_manager::AuthManager;
|
|
||||||
pub use self::login_manager::LoginManager;
|
pub use self::login_manager::LoginManager;
|
||||||
pub use self::client_connection::ClientConnection;
|
|
||||||
|
@ -1,259 +0,0 @@
|
|||||||
use std::fmt;
|
|
||||||
use std::net::UdpSocket;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::io::Cursor;
|
|
||||||
use std::thread;
|
|
||||||
use std::sync::mpsc;
|
|
||||||
use std::sync::{Arc, RwLock, Mutex};
|
|
||||||
|
|
||||||
use num_derive::FromPrimitive;
|
|
||||||
use num_traits::FromPrimitive;
|
|
||||||
use num_derive::ToPrimitive;
|
|
||||||
use num_traits::ToPrimitive;
|
|
||||||
|
|
||||||
use crate::utils::HandshakePacket;
|
|
||||||
use crate::utils::DataPacket;
|
|
||||||
use crate::server::ClientConnection;
|
|
||||||
use crate::server::GameServer;
|
|
||||||
use crate::server::AuthManager;
|
|
||||||
|
|
||||||
use rs_ipc::{IpcMessage, PullSocket, PushSocket};
|
|
||||||
|
|
||||||
use proto::PacketHead;
|
|
||||||
use proto::GetPlayerTokenRsp;
|
|
||||||
//use proto::get_player_token_rsp;
|
|
||||||
|
|
||||||
use prost::Message;
|
|
||||||
|
|
||||||
use rs_ipc::{SubSocket, PubSocket};
|
|
||||||
|
|
||||||
use packet_processor::{PacketProcessor, EasilyUnpackable};
|
|
||||||
use crate::node::NodeConfig;
|
|
||||||
|
|
||||||
extern crate kcp;
|
|
||||||
|
|
||||||
/*
|
|
||||||
This is used to convert async operations into sync ones
|
|
||||||
*/
|
|
||||||
trait Block {
|
|
||||||
fn wait(self) -> <Self as futures::Future>::Output
|
|
||||||
where Self: Sized, Self: futures::Future
|
|
||||||
{
|
|
||||||
futures::executor::block_on(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F,T> Block for F
|
|
||||||
where F: futures::Future<Output = T>
|
|
||||||
{}
|
|
||||||
|
|
||||||
// -------------
|
|
||||||
|
|
||||||
pub struct NetworkServer {
|
|
||||||
socket: UdpSocket,
|
|
||||||
clients: Arc<Mutex<HashMap<u32,ClientConnection>>>,
|
|
||||||
node_config: NodeConfig,
|
|
||||||
packets_to_process_tx: PubSocket,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct NetworkServerError {
|
|
||||||
reason: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NetworkServerError {
|
|
||||||
pub fn new(reason: &str) -> NetworkServerError {
|
|
||||||
return NetworkServerError {reason: reason.to_string()};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for NetworkServerError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "NetworkServerError: {}", self.reason)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NetworkServer {
|
|
||||||
pub fn new(host: &str, port: i16) -> Result<NetworkServer, NetworkServerError> {
|
|
||||||
let node_config = NodeConfig::new();
|
|
||||||
|
|
||||||
let mut packets_to_process_tx = node_config.bind_in_queue().unwrap();
|
|
||||||
|
|
||||||
let gs = NetworkServer {
|
|
||||||
socket: match UdpSocket::bind(format!("{}:{}", host, port).to_string()) {
|
|
||||||
Ok(socket) => socket,
|
|
||||||
Err(e) => return Err(NetworkServerError::new(format!("Failed to bind socket: {}", e).as_str())),
|
|
||||||
},
|
|
||||||
clients: Arc::new(Mutex::new(HashMap::new())),
|
|
||||||
node_config: node_config,
|
|
||||||
packets_to_process_tx: packets_to_process_tx,
|
|
||||||
};
|
|
||||||
|
|
||||||
print!("Connection established\n");
|
|
||||||
|
|
||||||
return Ok(gs);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run(&mut self) -> Result<i16, NetworkServerError> {
|
|
||||||
print!("Starting server\n");
|
|
||||||
|
|
||||||
let mut packets_to_send_rx = self.node_config.bind_out_queue().unwrap();
|
|
||||||
|
|
||||||
let clients = self.clients.clone();
|
|
||||||
let mut auth_manager = Arc::new(Mutex::new(AuthManager::new(&self.node_config)));
|
|
||||||
let am = auth_manager.clone();
|
|
||||||
|
|
||||||
let packet_relaying_thread = thread::spawn(move || {
|
|
||||||
loop {
|
|
||||||
let IpcMessage(packet_id, user_id, metadata, data) = packets_to_send_rx.recv().unwrap();
|
|
||||||
|
|
||||||
let conv = match packet_id {
|
|
||||||
proto::PacketId::GetPlayerTokenRsp => user_id, // Mapping is not performed on those
|
|
||||||
_ => am.lock().unwrap().resolve_uid(user_id).unwrap_or_else(|| panic!("Unknown user ID {}!", user_id)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let data_packet = DataPacket::new(packet_id.clone() as u16, metadata, data.clone());
|
|
||||||
|
|
||||||
match clients.lock().unwrap().get_mut(&conv) {
|
|
||||||
Some(client) => {
|
|
||||||
let bytes = data_packet.to_bytes();
|
|
||||||
client.send_udp_packet(&bytes);
|
|
||||||
|
|
||||||
if packet_id == proto::PacketId::GetPlayerTokenRsp {
|
|
||||||
// TODO: a bit hacky!
|
|
||||||
let token_rsp: GetPlayerTokenRsp = EasilyUnpackable::from(&data);
|
|
||||||
client.update_key(token_rsp.secret_key_seed);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => panic!("Unknown client conv: {}", conv),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let game_thread = thread::spawn(move || {
|
|
||||||
let node_config = NodeConfig::new();
|
|
||||||
let mut gs = GameServer::new(&node_config);
|
|
||||||
gs.run();
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut buffer = [0u8; 65536];
|
|
||||||
|
|
||||||
loop {
|
|
||||||
match self.socket.recv_from(&mut buffer) {
|
|
||||||
Ok( (bytes_number, source_address) ) => self.process_udp_packet(source_address, &buffer[..bytes_number], &mut auth_manager),
|
|
||||||
Err(e) => panic!("Failed to receive data: {}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//packet_relaying_thread.join().unwrap();
|
|
||||||
|
|
||||||
return Ok(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_udp_packet(&mut self, source_address: SocketAddr, packet_bytes: &[u8], auth_manager: &mut Arc<Mutex<AuthManager>>) {
|
|
||||||
//print!("Received packet! Len = {}\n", packet_bytes.len());
|
|
||||||
|
|
||||||
let hs_packet = HandshakePacket::new(packet_bytes);
|
|
||||||
|
|
||||||
match hs_packet {
|
|
||||||
Ok(hs_packet) => {
|
|
||||||
//print!("Received handshake packet: {:#?}\n", hs_packet);
|
|
||||||
if hs_packet.is_connect() {
|
|
||||||
//print!("Sending reply to CONNECT\n");
|
|
||||||
// TODO: assign conv and token!
|
|
||||||
let conv = 0x96969696u32;
|
|
||||||
let token = 0x42424242u32;
|
|
||||||
|
|
||||||
let reply = HandshakePacket::new_conv(conv, token);
|
|
||||||
|
|
||||||
let mut client = ClientConnection::new(self.socket.try_clone().unwrap(), conv, token);
|
|
||||||
client.update_source(source_address);
|
|
||||||
|
|
||||||
self.clients.lock().unwrap().insert(conv, client);
|
|
||||||
|
|
||||||
self.socket.send_to(&reply.to_bytes(), source_address).expect("Failed to send data!");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
//print!("Error constructing handshake: {:#?}", e);
|
|
||||||
let conv = kcp::get_conv(packet_bytes);
|
|
||||||
|
|
||||||
let packets = match self.clients.lock().unwrap().get_mut(&conv) {
|
|
||||||
Some(client) => {
|
|
||||||
client.update_source(source_address);
|
|
||||||
|
|
||||||
client.process_udp_packet(packet_bytes)
|
|
||||||
}
|
|
||||||
None => panic!("Unknown client conv: {}", conv),
|
|
||||||
};
|
|
||||||
|
|
||||||
for packet in packets.iter() {
|
|
||||||
self.process_game_packet(conv, packet, auth_manager);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_game_packet(&mut self, conv: u32, packet: &[u8], auth_manager: &mut Arc<Mutex<AuthManager>>) {
|
|
||||||
let data = match DataPacket::new_from_bytes(packet) {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(e) => panic!("Malformed data packet: {:#?}!", e),
|
|
||||||
};
|
|
||||||
|
|
||||||
let head = match PacketHead::decode(&mut Cursor::new(&data.metadata)) {
|
|
||||||
Ok(head) => head,
|
|
||||||
Err(e) => panic!("Malformed packet header: {:#?}!", e),
|
|
||||||
};
|
|
||||||
|
|
||||||
let packet_id: proto::PacketId = match FromPrimitive::from_u16(data.packet_id) {
|
|
||||||
Some(packet_id) => packet_id,
|
|
||||||
None => {
|
|
||||||
println!("Skipping unknown packet ID {}", data.packet_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let user_id = match packet_id {
|
|
||||||
proto::PacketId::GetPlayerTokenReq => {
|
|
||||||
auth_manager.lock().unwrap().process(conv, packet_id, data.metadata, data.data);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
_ => match auth_manager.lock().unwrap().resolve_conv(conv) {
|
|
||||||
None => {
|
|
||||||
println!("Unknown user with conv {}! Skipping", conv);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
Some(user_id) => user_id,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if packet_id == proto::PacketId::UnionCmdNotify {
|
|
||||||
let union: proto::UnionCmdNotify = EasilyUnpackable::from(&data.data);
|
|
||||||
for u_cmd in union.cmd_list.into_iter() {
|
|
||||||
self.send_packet_to_process(user_id, u_cmd.message_id as u16, &data.metadata, &u_cmd.body);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.send_packet_to_process(user_id, data.packet_id, &data.metadata, &data.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_packet_to_process(&mut self, user_id: u32, packet_id: u16, metadata: &[u8], data: &[u8])
|
|
||||||
{
|
|
||||||
/*let sender: &mut PubSocket = match &self.packets_to_process_tx {
|
|
||||||
Some(mut sender) => &mut sender,
|
|
||||||
None => panic!("Processing queue wasn't set up!"),
|
|
||||||
};*/
|
|
||||||
|
|
||||||
let packet_id: proto::PacketId = match FromPrimitive::from_u16(packet_id) {
|
|
||||||
Some(packet_id) => packet_id,
|
|
||||||
None => {
|
|
||||||
println!("Skipping unknown packet ID {}", packet_id);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("Got packet {:?}", packet_id);
|
|
||||||
self.packets_to_process_tx.send( IpcMessage(packet_id, user_id, metadata.to_vec(), data.to_vec()) );
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,10 +16,11 @@ use packet_processor::*;
|
|||||||
use serde_json::de::Read;
|
use serde_json::de::Read;
|
||||||
use crate::{DatabaseManager, JsonManager, LuaManager};
|
use crate::{DatabaseManager, JsonManager, LuaManager};
|
||||||
use crate::entitymanager::EntityManager;
|
use crate::entitymanager::EntityManager;
|
||||||
use crate::utils::{IdManager, TimeManager};
|
use crate::utils::{IdManager};
|
||||||
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
use crate::luamanager::Vector;
|
use crate::luamanager::Vector;
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
|
|
||||||
#[packet_processor(
|
#[packet_processor(
|
||||||
CombatInvocationsNotify,
|
CombatInvocationsNotify,
|
||||||
|
@ -5,7 +5,7 @@ use crate::{DatabaseManager, JsonManager};
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
use packet_processor::*;
|
use packet_processor::*;
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
|
|
||||||
pub struct InventorySubsystem {
|
pub struct InventorySubsystem {
|
||||||
packets_to_send_tx: PushSocket,
|
packets_to_send_tx: PushSocket,
|
||||||
|
@ -15,8 +15,9 @@ use packet_processor_macro::*;
|
|||||||
use packet_processor::*;
|
use packet_processor::*;
|
||||||
use serde_json::de::Read;
|
use serde_json::de::Read;
|
||||||
use crate::{DatabaseManager, JsonManager, LuaManager};
|
use crate::{DatabaseManager, JsonManager, LuaManager};
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
use crate::utils::{IdManager, TimeManager};
|
use crate::utils::{IdManager};
|
||||||
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
#[packet_processor(
|
#[packet_processor(
|
||||||
NpcTalkReq,
|
NpcTalkReq,
|
||||||
|
@ -15,8 +15,9 @@ use packet_processor_macro::*;
|
|||||||
use packet_processor::*;
|
use packet_processor::*;
|
||||||
use serde_json::de::Read;
|
use serde_json::de::Read;
|
||||||
use crate::{DatabaseManager, JsonManager, LuaManager};
|
use crate::{DatabaseManager, JsonManager, LuaManager};
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
use crate::utils::{IdManager, TimeManager};
|
use crate::utils::{IdManager};
|
||||||
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
#[packet_processor(
|
#[packet_processor(
|
||||||
PlayerSetPauseReq,
|
PlayerSetPauseReq,
|
||||||
|
@ -15,8 +15,9 @@ use packet_processor_macro::*;
|
|||||||
use packet_processor::*;
|
use packet_processor::*;
|
||||||
use serde_json::de::Read;
|
use serde_json::de::Read;
|
||||||
use crate::{DatabaseManager, JsonManager, LuaManager};
|
use crate::{DatabaseManager, JsonManager, LuaManager};
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
use crate::utils::{IdManager, TimeManager};
|
use crate::utils::{IdManager};
|
||||||
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
#[packet_processor(
|
#[packet_processor(
|
||||||
GetSceneAreaReq,
|
GetSceneAreaReq,
|
||||||
|
@ -15,9 +15,10 @@ use packet_processor_macro::*;
|
|||||||
use packet_processor::*;
|
use packet_processor::*;
|
||||||
use serde_json::de::Read;
|
use serde_json::de::Read;
|
||||||
use crate::{DatabaseManager, JsonManager, LuaManager};
|
use crate::{DatabaseManager, JsonManager, LuaManager};
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
use crate::subsystems::InventorySubsystem;
|
use crate::subsystems::InventorySubsystem;
|
||||||
use crate::utils::{IdManager, TimeManager};
|
use crate::utils::{IdManager};
|
||||||
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
#[packet_processor(
|
#[packet_processor(
|
||||||
GetShopReq,
|
GetShopReq,
|
||||||
|
@ -17,8 +17,9 @@ use packet_processor_macro::*;
|
|||||||
use packet_processor::*;
|
use packet_processor::*;
|
||||||
use serde_json::de::Read;
|
use serde_json::de::Read;
|
||||||
use crate::{DatabaseManager, JsonManager, LuaManager};
|
use crate::{DatabaseManager, JsonManager, LuaManager};
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
use crate::utils::{IdManager, TimeManager};
|
use crate::utils::{IdManager};
|
||||||
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
#[packet_processor(
|
#[packet_processor(
|
||||||
GetPlayerBlacklistReq,
|
GetPlayerBlacklistReq,
|
||||||
|
@ -17,8 +17,9 @@ use serde_json::de::Read;
|
|||||||
use crate::{DatabaseManager, JsonManager, LuaManager};
|
use crate::{DatabaseManager, JsonManager, LuaManager};
|
||||||
use crate::entitymanager::EntityManager;
|
use crate::entitymanager::EntityManager;
|
||||||
use crate::luamanager::Vector;
|
use crate::luamanager::Vector;
|
||||||
use crate::node::NodeConfig;
|
use rs_nodeconf::NodeConfig;
|
||||||
use crate::utils::{IdManager, TimeManager};
|
use crate::utils::{IdManager};
|
||||||
|
use rs_utils::TimeManager;
|
||||||
|
|
||||||
#[packet_processor(
|
#[packet_processor(
|
||||||
SceneTransToPointReq,
|
SceneTransToPointReq,
|
||||||
|
@ -1,90 +0,0 @@
|
|||||||
use std::fmt;
|
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct DataDecError {
|
|
||||||
reason: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(packed)]
|
|
||||||
pub struct DataPacketSmallest // Not actually used, just represents the general structure
|
|
||||||
{
|
|
||||||
start_magic: u16,
|
|
||||||
packet_id: u16,
|
|
||||||
metadata_size: u16,
|
|
||||||
data_size: u32,
|
|
||||||
//metadata: [0u8; metadata_size],
|
|
||||||
//data: [0u8; data_size],
|
|
||||||
end_magic: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct DataPacket
|
|
||||||
{
|
|
||||||
pub packet_id: u16,
|
|
||||||
pub metadata: Vec<u8>,
|
|
||||||
pub data: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DataPacket {
|
|
||||||
const DATA_MAGIC_START: u16 = 0x4567;
|
|
||||||
const DATA_MAGIC_END: u16 = 0x89AB;
|
|
||||||
|
|
||||||
pub fn new(packet_id: u16, metadata: Vec<u8>, data: Vec<u8>) -> DataPacket {
|
|
||||||
return DataPacket {
|
|
||||||
packet_id: packet_id,
|
|
||||||
data: data,
|
|
||||||
metadata: metadata,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_from_bytes(raw_data: &[u8]) -> Result<DataPacket, DataDecError> {
|
|
||||||
if raw_data.len() < std::mem::size_of::<DataPacketSmallest>() {
|
|
||||||
return Err(DataDecError {reason: "Size is too small!".to_string()});
|
|
||||||
}
|
|
||||||
|
|
||||||
// unwrap() here are valid as we're cutting exactly 4 bytes of data
|
|
||||||
let start_magic = u16::from_be_bytes(raw_data[0..2].try_into().unwrap());
|
|
||||||
let end_magic = u16::from_be_bytes(raw_data[raw_data.len()-2..].try_into().unwrap());
|
|
||||||
|
|
||||||
if (start_magic == DataPacket::DATA_MAGIC_START) && (end_magic == DataPacket::DATA_MAGIC_END) {
|
|
||||||
let packet_id = u16::from_be_bytes(raw_data[2..4].try_into().unwrap());
|
|
||||||
let metadata_size = u16::from_be_bytes(raw_data[4..6].try_into().unwrap()) as usize;
|
|
||||||
let data_size = u32::from_be_bytes(raw_data[6..10].try_into().unwrap()) as usize;
|
|
||||||
|
|
||||||
let expected_size = std::mem::size_of::<DataPacketSmallest>() + metadata_size + data_size;
|
|
||||||
|
|
||||||
if raw_data.len() != expected_size {
|
|
||||||
return Err(DataDecError {reason: format!("Wrong packet size: expected {}, got {} (header {}, payload {})!", expected_size, raw_data.len(), std::mem::size_of::<DataPacketSmallest>(), metadata_size + data_size)});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(DataPacket {
|
|
||||||
packet_id: packet_id,
|
|
||||||
metadata: raw_data[10..metadata_size+10].to_owned(),
|
|
||||||
data: raw_data[metadata_size+10..metadata_size+data_size+10].to_owned(),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Err(DataDecError {reason: format!("Unknown magic: 0x{:x} 0x{:x}", start_magic, end_magic),});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
|
||||||
let mut ret = Vec::with_capacity(std::mem::size_of::<DataPacketSmallest>() + self.data.len() + self.metadata.len());
|
|
||||||
|
|
||||||
ret.extend_from_slice(&DataPacket::DATA_MAGIC_START.to_be_bytes());
|
|
||||||
ret.extend_from_slice(&self.packet_id.to_be_bytes());
|
|
||||||
ret.extend_from_slice(&(self.metadata.len() as u16).to_be_bytes());
|
|
||||||
ret.extend_from_slice(&(self.data.len() as u32).to_be_bytes());
|
|
||||||
ret.extend_from_slice(&self.metadata);
|
|
||||||
ret.extend_from_slice(&self.data);
|
|
||||||
ret.extend_from_slice(&DataPacket::DATA_MAGIC_END.to_be_bytes());
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for DataPacket {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "packet")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
use std::fmt;
|
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct HandshakeDecError {
|
|
||||||
reason: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct HandshakePacket
|
|
||||||
{
|
|
||||||
start_magic: u32,
|
|
||||||
param1: u32,
|
|
||||||
param2: u32,
|
|
||||||
data: u32,
|
|
||||||
end_magic: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HandshakePacket {
|
|
||||||
const HS_MAGIC_CONNECT_START: u32 = 0x000000FF;
|
|
||||||
const HS_MAGIC_CONNECT_END: u32 = 0xFFFFFFFF;
|
|
||||||
const HS_MAGIC_SEND_CONV_START: u32 = 0x00000145;
|
|
||||||
const HS_MAGIC_SEND_CONV_END: u32 = 0x14514545;
|
|
||||||
const HS_MAGIC_DISCONNECT_START: u32 = 0x00000194;
|
|
||||||
const HS_MAGIC_DISCONNECT_END: u32 = 0x19419494;
|
|
||||||
|
|
||||||
const HS_CONNECTION_DATA: u32 = 1234567890;
|
|
||||||
|
|
||||||
pub fn new(raw_data: &[u8]) -> Result<HandshakePacket, HandshakeDecError> {
|
|
||||||
if raw_data.len() != std::mem::size_of::<HandshakePacket>() {
|
|
||||||
return Err(HandshakeDecError {reason: "Size mismatch!".to_string()});
|
|
||||||
}
|
|
||||||
|
|
||||||
// unwrap() here are valid as we're cutting exactly 4 bytes of data
|
|
||||||
let start_magic = u32::from_be_bytes(raw_data[0..4].try_into().unwrap());
|
|
||||||
let param1 = u32::from_be_bytes(raw_data[4..8].try_into().unwrap());
|
|
||||||
let param2 = u32::from_be_bytes(raw_data[8..12].try_into().unwrap());
|
|
||||||
let data = u32::from_be_bytes(raw_data[12..16].try_into().unwrap());
|
|
||||||
let end_magic = u32::from_be_bytes(raw_data[16..20].try_into().unwrap());
|
|
||||||
|
|
||||||
if (start_magic == HandshakePacket::HS_MAGIC_CONNECT_START) && (end_magic == HandshakePacket::HS_MAGIC_CONNECT_END) ||
|
|
||||||
(start_magic == HandshakePacket::HS_MAGIC_SEND_CONV_START) && (end_magic == HandshakePacket::HS_MAGIC_SEND_CONV_END) ||
|
|
||||||
(start_magic == HandshakePacket::HS_MAGIC_DISCONNECT_START) && (end_magic == HandshakePacket::HS_MAGIC_DISCONNECT_END) {
|
|
||||||
|
|
||||||
return Ok(HandshakePacket {
|
|
||||||
start_magic: start_magic,
|
|
||||||
param1: param1,
|
|
||||||
param2: param2,
|
|
||||||
data: data,
|
|
||||||
end_magic: end_magic,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Err(HandshakeDecError {reason: format!("Unknown magic: 0x{:x} 0x{:x}", start_magic, end_magic),});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_connect(&self) -> bool {
|
|
||||||
return (self.start_magic == HandshakePacket::HS_MAGIC_CONNECT_START) &&
|
|
||||||
(self.end_magic == HandshakePacket::HS_MAGIC_CONNECT_END) &&
|
|
||||||
(self.data == HandshakePacket::HS_CONNECTION_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_conv(conv: u32, token: u32) -> HandshakePacket {
|
|
||||||
HandshakePacket {
|
|
||||||
start_magic: HandshakePacket::HS_MAGIC_SEND_CONV_START,
|
|
||||||
param1: conv,
|
|
||||||
param2: token,
|
|
||||||
data: HandshakePacket::HS_CONNECTION_DATA,
|
|
||||||
end_magic: HandshakePacket::HS_MAGIC_SEND_CONV_END,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
|
||||||
let mut ret = Vec::with_capacity(std::mem::size_of::<HandshakePacket>());
|
|
||||||
|
|
||||||
ret.extend_from_slice(&self.start_magic.to_be_bytes());
|
|
||||||
ret.extend_from_slice(&self.param1.to_be_bytes());
|
|
||||||
ret.extend_from_slice(&self.param2.to_be_bytes());
|
|
||||||
ret.extend_from_slice(&self.data.to_be_bytes());
|
|
||||||
ret.extend_from_slice(&self.end_magic.to_be_bytes());
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for HandshakePacket {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "packet")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +1,9 @@
|
|||||||
mod handshake_packet;
|
|
||||||
mod data_packet;
|
|
||||||
mod id_manager;
|
mod id_manager;
|
||||||
mod time_manager;
|
|
||||||
mod avatar_builder;
|
mod avatar_builder;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod remapper;
|
mod remapper;
|
||||||
|
|
||||||
pub use self::handshake_packet::HandshakePacket;
|
|
||||||
pub use self::data_packet::DataPacket;
|
|
||||||
pub use self::id_manager::IdManager;
|
pub use self::id_manager::IdManager;
|
||||||
pub use self::time_manager::TimeManager;
|
|
||||||
pub use self::remapper::Remapper;
|
pub use self::remapper::Remapper;
|
||||||
pub use self::avatar_builder::AvatarBuilder;
|
pub use self::avatar_builder::AvatarBuilder;
|
@ -1,28 +0,0 @@
|
|||||||
use std::time::SystemTime;
|
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
|
||||||
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
|
||||||
|
|
||||||
pub struct TimeManager {
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TimeManager {
|
|
||||||
pub fn duration_since(time_point: SystemTime) -> u64 {
|
|
||||||
SystemTime::now().duration_since(time_point).unwrap().as_millis().try_into().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn timestamp() -> u64 {
|
|
||||||
return Self::duration_since(SystemTime::UNIX_EPOCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> std::result::Result<Option<NaiveDateTime>, D::Error> {
|
|
||||||
let time: String = Deserialize::deserialize(deserializer)?;
|
|
||||||
|
|
||||||
if time.is_empty() {
|
|
||||||
Ok(None)
|
|
||||||
} else {
|
|
||||||
Ok(Some(NaiveDateTime::parse_from_str(&time, "%Y-%m-%d %H:%M:%S").map_err(D::Error::custom)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user