diff options
| author | Fuwn <[email protected]> | 2021-05-17 10:16:42 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2021-05-17 10:16:42 +0000 |
| commit | 1b482ab22031ab9a895b2567ba10a2e553752303 (patch) | |
| tree | db4874c46b25655ba7c94b0ab435fdb0d681af55 /src/server | |
| parent | refactor(global): whirl_config modulized (diff) | |
| download | whirl-1b482ab22031ab9a895b2567ba10a2e553752303.tar.xz whirl-1b482ab22031ab9a895b2567ba10a2e553752303.zip | |
refactor(global): even more modules becoming crates
I did multiple checks and **yes**, everything still works perfectly fine.
Diffstat (limited to 'src/server')
30 files changed, 0 insertions, 1331 deletions
diff --git a/src/server/cmd/commands/action.rs b/src/server/cmd/commands/action.rs deleted file mode 100644 index 8d1fb0b..0000000 --- a/src/server/cmd/commands/action.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -// TODO: of2m-ify -// -// Of2m-ifying isn't much of a priority right now as the whole action ordeal -// hasn't been fully dissected yet. Once more is known about the inner working -// of actions, it will be of2m-ified. - -use bytes::{BufMut, BytesMut}; - -pub fn create_action() -> Vec<u8> { - let mut command = BytesMut::new(); - - command.put_slice(&[ - 0x01, 0x11, 0x00, 0x05, 0x54, 0x52, 0x41, 0x44, 0x45, 0x07, 0x26, 0x7c, 0x2b, 0x69, 0x6e, 0x76, - 0x3e, - ]); - - // Convert to vector and insert the length - let mut command_as_vec = command.to_vec(); - command_as_vec.insert(0, command.len() as u8 + 1); - - // Return bytes - command_as_vec -} diff --git a/src/server/cmd/commands/buddy_list.rs b/src/server/cmd/commands/buddy_list.rs deleted file mode 100644 index 7e9722a..0000000 --- a/src/server/cmd/commands/buddy_list.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use std::str::from_utf8; - -use bytes::{BufMut, BytesMut}; - -use crate::server::cmd::{ - constants::BUDDYLISTNOTIFY, - extendable::{Creatable, Parsable}, -}; - -#[derive(Clone)] -pub struct BuddyList { - pub buddy: String, - pub add: i8, -} -impl Parsable for BuddyList { - fn parse(data: Vec<u8>) -> Self { - Self { - buddy: from_utf8(&data[4..data[0] as usize - 1]) - .unwrap() - .to_string(), - - // Get the last byte - add: data[data[0] as usize - 1] as i8, - } - } -} -impl Creatable for BuddyList { - fn create(self) -> Vec<u8> { - let mut command = BytesMut::new(); - - // Header - command.put_u8(0x01); // ObjId - command.put_i8(BUDDYLISTNOTIFY as i8); // Type - - // Content - command.put_u8(self.buddy.len() as u8); // Buddy (name) length - command.put_slice(self.buddy.as_bytes()); // Buddy (name) - command.put_u8(self.add as u8); // "Is buddy logged on?" (?) - - let mut command_as_vec = command.to_vec(); - command_as_vec.insert(0, command.len() as u8 + 1); - - command_as_vec - } -} diff --git a/src/server/cmd/commands/mod.rs b/src/server/cmd/commands/mod.rs deleted file mode 100644 index 49758c2..0000000 --- a/src/server/cmd/commands/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub mod action; -pub mod buddy_list; -pub mod property; -pub mod redirect_id; -pub mod room_id_request; -pub mod subscribe_distance; -pub mod subscribe_room; -pub mod teleport; -pub mod text; diff --git a/src/server/cmd/commands/property/create.rs b/src/server/cmd/commands/property/create.rs deleted file mode 100644 index 88a9293..0000000 --- a/src/server/cmd/commands/property/create.rs +++ /dev/null @@ -1,168 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -// TODO: of2m-ify? - -use whirl_config::Config; - -use crate::server::{ - cmd::constants::{PROPUPD, SESSINIT}, - net::{ - constants::{ - VAR_APPNAME, - VAR_CHANNEL, - VAR_ERROR, - VAR_EXTERNAL_HTTP_SERVER, - VAR_MAIL_DOMAIN, - VAR_PRIV, - VAR_PROTOCOL, - VAR_SCRIPT_SERVER, - VAR_SERIAL, - VAR_SERVERTYPE, - VAR_SMTP_SERVER, - VAR_UPDATETIME, - }, - converter::property_list_to_bytes, - structure::NetworkProperty, - }, -}; - -pub fn create_property_update_as_distributor() -> Vec<u8> { - property_list_to_bytes( - PROPUPD, - 0xFF, - vec![ - NetworkProperty { - prop_id: VAR_MAIL_DOMAIN, - value: "worlds3d.com".to_string(), - }, - NetworkProperty { - prop_id: VAR_SMTP_SERVER, - value: "mail.worlds.net:25".to_string(), - }, - NetworkProperty { - prop_id: VAR_SCRIPT_SERVER, - value: "http://www-dynamic.us.worlds.net/cgi-bin".to_string(), - }, - NetworkProperty { - prop_id: VAR_EXTERNAL_HTTP_SERVER, - value: "http://www-static.us.worlds.net".to_string(), - }, - NetworkProperty { - prop_id: VAR_SERVERTYPE, - value: "1".to_string(), - }, - NetworkProperty { - prop_id: VAR_PROTOCOL, - value: "24".to_string(), - }, - NetworkProperty { - prop_id: VAR_APPNAME, - value: Config::get().whirlsplash.worldsmaster_username, - }, - ], - ) -} - -pub fn create_property_update_as_hub() -> Vec<u8> { - property_list_to_bytes( - PROPUPD, - 0xFF, - vec![ - NetworkProperty { - prop_id: VAR_UPDATETIME, - value: "1000000".to_string(), - }, - NetworkProperty { - prop_id: VAR_MAIL_DOMAIN, - value: "worlds3d.com".to_string(), - }, - NetworkProperty { - prop_id: VAR_SMTP_SERVER, - value: "mail.worlds.net:25".to_string(), - }, - NetworkProperty { - prop_id: VAR_SCRIPT_SERVER, - value: "http://www-dynamic.us.worlds.net/cgi-bin".to_string(), - }, - NetworkProperty { - prop_id: VAR_EXTERNAL_HTTP_SERVER, - value: "http://www-static.us.worlds.net".to_string(), - }, - NetworkProperty { - prop_id: VAR_SERVERTYPE, - value: "3".to_string(), - }, - NetworkProperty { - prop_id: VAR_PROTOCOL, - value: "24".to_string(), - }, - NetworkProperty { - prop_id: VAR_APPNAME, - value: Config::get().whirlsplash.worldsmaster_username, - }, - ], - ) -} - -pub fn create_property_request_as_distributor() -> Vec<u8> { - property_list_to_bytes( - SESSINIT as i32, - 0x01, - vec![ - NetworkProperty { - prop_id: VAR_ERROR, - value: "0".to_string(), - }, - NetworkProperty { - prop_id: VAR_APPNAME, - value: Config::get().whirlsplash.worldsmaster_username, - }, - NetworkProperty { - prop_id: VAR_PROTOCOL, - value: "24".to_string(), - }, - NetworkProperty { - prop_id: VAR_SERVERTYPE, - value: "1".to_string(), - }, - NetworkProperty { - prop_id: VAR_SERIAL, - value: "DWLV000000000000".to_string(), - }, - NetworkProperty { - prop_id: VAR_PRIV, - value: "0".to_string(), - }, - NetworkProperty { - prop_id: VAR_CHANNEL, - value: "dimension-1".to_string(), - }, - ], - ) -} - -pub fn create_property_request_as_hub() -> Vec<u8> { - property_list_to_bytes( - SESSINIT as i32, - 0x01, - vec![ - NetworkProperty { - prop_id: VAR_ERROR, - value: "0".to_string(), - }, - NetworkProperty { - prop_id: VAR_SERVERTYPE, - value: "3".to_string(), - }, - NetworkProperty { - prop_id: VAR_UPDATETIME, - value: "1000000".to_string(), - }, - NetworkProperty { - prop_id: VAR_PROTOCOL, - value: "24".to_string(), - }, - ], - ) -} diff --git a/src/server/cmd/commands/property/mod.rs b/src/server/cmd/commands/property/mod.rs deleted file mode 100644 index 83b015b..0000000 --- a/src/server/cmd/commands/property/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub mod create; -pub mod parse; diff --git a/src/server/cmd/commands/property/parse.rs b/src/server/cmd/commands/property/parse.rs deleted file mode 100644 index ef587fe..0000000 --- a/src/server/cmd/commands/property/parse.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use crate::server::net::structure::NetworkProperty; - -pub fn find_property_in_property_list( - property_list: &[NetworkProperty], - property: i32, -) -> &NetworkProperty { - property_list - .iter() - .find(|i| i.prop_id == property) - .unwrap() -} diff --git a/src/server/cmd/commands/redirect_id.rs b/src/server/cmd/commands/redirect_id.rs deleted file mode 100644 index edaf46e..0000000 --- a/src/server/cmd/commands/redirect_id.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::{BufMut, BytesMut}; -use whirl_config::Config; - -use crate::server::cmd::{constants::REDIRID, extendable::Creatable}; - -#[derive(Debug)] -pub struct RedirectId { - pub room_name: String, - pub room_number: i8, -} -impl Creatable for RedirectId { - fn create(self) -> Vec<u8> { - let mut command = BytesMut::new(); - - // Header - command.put_u8(0x01); // ObjId - command.put_u8(REDIRID as u8); // Type - - // Content - command.put_u8(self.room_name.len() as u8); // Room name length - command.put_slice(self.room_name.as_bytes()); // Room name - // command.put_u8(0x00); // Unimplemented byte (?) - // command.put_u8(room_id); // Room ID - command.put_u16(self.room_number as u16); // Room ID - - // IP - for byte in Config::get().whirlsplash.ip.split('.') { - command.put_u8(byte.parse::<u8>().unwrap()); - } - command.put_u16(Config::get().hub.port as u16); // Port - - // Length - let mut command_as_vec = command.to_vec(); - command_as_vec.insert(0, command.len() as u8 + 1); - - // Return - command_as_vec - } -} diff --git a/src/server/cmd/commands/room_id_request.rs b/src/server/cmd/commands/room_id_request.rs deleted file mode 100644 index cc8dbeb..0000000 --- a/src/server/cmd/commands/room_id_request.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use std::str::from_utf8; - -use crate::server::cmd::extendable::Parsable; - -#[derive(Debug)] -pub struct RoomIdRequest { - pub room_name: String, -} -impl Parsable for RoomIdRequest { - fn parse(data: Vec<u8>) -> Self { - Self { - room_name: from_utf8(&data[4..data[0] as usize]).unwrap().to_string(), - } - } -} diff --git a/src/server/cmd/commands/subscribe_distance.rs b/src/server/cmd/commands/subscribe_distance.rs deleted file mode 100644 index 66f4241..0000000 --- a/src/server/cmd/commands/subscribe_distance.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use byteorder::{BigEndian, ReadBytesExt}; -use bytes::{Buf, BytesMut}; - -use crate::server::cmd::extendable::Parsable; - -#[derive(Debug)] -pub struct SubscribeDistance { - pub distance: i16, - pub room_number: i16, -} -impl Parsable for SubscribeDistance { - fn parse(data: Vec<u8>) -> Self { - // https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8 - let mut data = BytesMut::from(data.as_slice()).reader(); - - Self { - distance: data.read_i16::<BigEndian>().unwrap(), - room_number: data.read_i16::<BigEndian>().unwrap(), - } - } -} diff --git a/src/server/cmd/commands/subscribe_room.rs b/src/server/cmd/commands/subscribe_room.rs deleted file mode 100644 index d936fff..0000000 --- a/src/server/cmd/commands/subscribe_room.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use byteorder::{BigEndian, ReadBytesExt}; -use bytes::{Buf, BytesMut}; - -use crate::server::cmd::extendable::Parsable; - -#[derive(Debug)] -pub struct SubscribeRoom { - pub room_number: i8, - pub x: f32, - pub y: f32, - pub z: f32, - pub distance: f32, -} -impl Parsable for SubscribeRoom { - fn parse(data: Vec<u8>) -> Self { - // https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8 - let mut data = BytesMut::from(data.as_slice()).reader(); - - Self { - room_number: data.read_i16::<BigEndian>().unwrap() as i8, - x: data.read_i16::<BigEndian>().unwrap() as i8 as f32, - y: data.read_i16::<BigEndian>().unwrap() as i8 as f32, - z: data.read_i16::<BigEndian>().unwrap() as i8 as f32, - distance: data.read_i16::<BigEndian>().unwrap() as i8 as f32, // + 100 - } - } -} diff --git a/src/server/cmd/commands/teleport.rs b/src/server/cmd/commands/teleport.rs deleted file mode 100644 index 7a2b55e..0000000 --- a/src/server/cmd/commands/teleport.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use byteorder::{BigEndian, ReadBytesExt}; -use bytes::{Buf, BytesMut}; - -use crate::server::cmd::extendable::Parsable; - -#[derive(Debug)] -pub struct Teleport { - pub room_id: i8, - pub exit_type: u8, - pub entry_type: u8, - pub x: f32, // i16 - pub y: f32, - pub z: f32, - pub direction: f32, -} -impl Parsable for Teleport { - fn parse(data: Vec<u8>) -> Self { - // https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8 - let mut data = BytesMut::from(data.as_slice()).reader(); - - Self { - room_id: data.read_u16::<BigEndian>().unwrap() as i8, - exit_type: data.read_u8().unwrap(), - entry_type: data.read_u8().unwrap(), - x: data.read_i16::<BigEndian>().unwrap() as f32, - y: data.read_i16::<BigEndian>().unwrap() as f32, - z: data.read_i16::<BigEndian>().unwrap() as f32, - direction: data.read_i16::<BigEndian>().unwrap() as f32, - } - } -} diff --git a/src/server/cmd/commands/text.rs b/src/server/cmd/commands/text.rs deleted file mode 100644 index 5019fc1..0000000 --- a/src/server/cmd/commands/text.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use std::str::from_utf8; - -use bytes::{BufMut, BytesMut}; - -use crate::server::cmd::{ - constants::TEXT, - extendable::{Creatable, ParsableWithArguments}, -}; - -pub struct Text { - pub sender: String, - pub content: String, -} -impl Creatable for Text { - fn create(self) -> Vec<u8> { - let mut command = BytesMut::new(); - - // Header - command.put_u8(0x01); - command.put_i8(TEXT as i8); - - // Content - // TODO: Find a way to parse ObjIds. - // - // The below byte is suspected to be the sender's short ObjId. - command.put_i8(0x00); - - command.put_u8(self.sender.len() as u8); - command.put_slice(self.sender.as_bytes()); - command.put_u8(self.content.len() as u8); - command.put_slice(self.content.as_bytes()); - - // Convert to vector and insert the length - let mut command_as_vec = command.to_vec(); - command_as_vec.insert(0, command.len() as u8 + 1); - - // Return bytes - command_as_vec - } -} -impl ParsableWithArguments for Text { - /// The first and only element of `args` *should* be the username of the - /// sender. - /// - /// There isn't anything currently stopping someone from passing some other - /// value so that might be annoying at times. - /// - /// Realistically, this method is mostly static so the username will *always* - /// be passed properly unless someone intentionally commits breaking changes - /// on purpose regarding what is passed to to this method where called. - /// - /// It would be neat to have some sort of ability to statically check if the - /// `args` argument contains x number of elements at compile time or - /// something of the sort but the Rust RFC is probably not focused on that. - /// - /// So, right now, trust is in the developers' hands to make sure to pass the - /// right -- number -- of elements to `args`. - fn parse(data: Vec<u8>, args: &[&str]) -> Self { - Self { - sender: args[0].to_string(), - content: from_utf8(&data[6..]).unwrap().to_string(), - } - } -} diff --git a/src/server/cmd/constants.rs b/src/server/cmd/constants.rs deleted file mode 100644 index 22d29c1..0000000 --- a/src/server/cmd/constants.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub const LONGLOC: i32 = 1; -pub const STATE: i32 = 2; -pub const PROP: i32 = 3; -pub const SHORTLOC: i32 = 4; -pub const ROOMCHNG: i32 = 5; -pub const SESSINIT: i32 = 6; -pub const SESSEXIT: i32 = 7; -pub const APPINIT: i32 = 8; -pub const PROPREQ: i32 = 10; -pub const DISAPPR: i32 = 11; -pub const APPRACTR: i32 = 12; -pub const REGOBJID: i32 = 13; -pub const TEXT: i32 = 14; -pub const PROPSET: i32 = 15; -pub const PROPUPD: i32 = 16; -pub const WHISPER: i32 = 17; -pub const TELEPORT: i32 = 18; -pub const ROOMIDRQ: i32 = 20; -pub const ROOMID: i32 = 21; -pub const SUBSCRIB: i32 = 22; -pub const UNSUBSCR: i32 = 23; -pub const SUB_DIST: i32 = 24; // SUB-DIST -pub const REDIRECT: i32 = 25; -pub const REDIRID: i32 = 26; -pub const FINGREQ: i32 = 27; -pub const FINGREP: i32 = 28; -pub const BUDDYLISTUPDATE: i32 = 29; -pub const BUDDYLISTNOTIFY: i32 = 30; -pub const CHANNEL: i32 = 31; diff --git a/src/server/cmd/extendable.rs b/src/server/cmd/extendable.rs deleted file mode 100644 index e6f3c2b..0000000 --- a/src/server/cmd/extendable.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub trait Parsable { - fn parse(data: Vec<u8>) -> Self; -} - -pub trait Creatable { - fn create(self) -> Vec<u8>; -} - -/// Having to do this makes me with there was operator overloading in Rust. -/// -/// I *could* do this with a macro but since Text is the only struct that -/// implements this trait, it shouldn't be that big of a deal. -pub trait ParsableWithArguments { - fn parse(data: Vec<u8>, args: &[&str]) -> Self; -} diff --git a/src/server/cmd/mod.rs b/src/server/cmd/mod.rs deleted file mode 100644 index ef91de7..0000000 --- a/src/server/cmd/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub mod commands; - -pub mod constants; -pub mod extendable; -mod set_parser; -mod structure; diff --git a/src/server/cmd/set_parser.rs b/src/server/cmd/set_parser.rs deleted file mode 100644 index 6d11f04..0000000 --- a/src/server/cmd/set_parser.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use crate::server::cmd::structure::Command; - -/// Iterate over a command set in the from of bytes and return a list of -/// human-readable commands. -fn _parse_command_set(mut data: Vec<u8>) -> Vec<Command> { - let mut command_set = vec![]; - - // Iterate over all commands - loop { - // Check if any commands are present - if data.len() <= 2 { - break; - } - if data[0] == 0 { - break; - } - - let command_length = data[0]; - let mut command = Command { - length: command_length as i32, - obj_id: data[1] as i32, - id: data[2] as i32, - body: vec![], - }; - if command.length > 3 { - command.body = data[3..].to_owned(); - } - command_set.push(command); - - // Remove current command from the command set - data = data[command_length as usize..].to_vec(); - } - - // Return the human-readable command set - command_set -} diff --git a/src/server/cmd/structure.rs b/src/server/cmd/structure.rs deleted file mode 100644 index 23e91ca..0000000 --- a/src/server/cmd/structure.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub struct Command { - pub length: i32, - pub obj_id: i32, - pub id: i32, - pub body: Vec<u8>, -} -impl Command { - pub fn _new() -> Self { Command::default() } -} -impl Default for Command { - fn default() -> Self { - Command { - length: 0, - obj_id: 0, - id: 0, - body: vec![], - } - } -} diff --git a/src/server/distributor.rs b/src/server/distributor.rs deleted file mode 100644 index 4267a78..0000000 --- a/src/server/distributor.rs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -//! The distributor functions as bare-minimal -//! [AutoServer](http://dev.worlds.net/private/GammaDocs/WorldServer.html#AutoServer). -//! -//! It intercepts a client and distributes it to a -//! [RoomServer](http://dev.worlds.net/private/GammaDocs/WorldServer.html#RoomServer). -//! -//! This is not meant to be a high performant section of code as the distributor -//! is only meant to handle the initial and brief session initialization of the -//! client. - -use std::{error::Error, net::SocketAddr, sync::Arc}; - -use tokio::{io::AsyncWriteExt, net::TcpStream, sync::Mutex}; -use tokio_stream::StreamExt; -use tokio_util::codec::{BytesCodec, Decoder}; -use whirl_config::Config; - -use crate::server::{ - cmd::{ - commands::{ - action::create_action, - buddy_list::BuddyList, - property::{ - create::{create_property_request_as_distributor, create_property_update_as_distributor}, - parse::find_property_in_property_list, - }, - redirect_id::RedirectId, - room_id_request::RoomIdRequest, - text::Text, - }, - constants::*, - extendable::{Creatable, Parsable}, - }, - interaction::{peer::Peer, shared::Shared}, - net::{constants::VAR_USERNAME, property_parser::parse_network_property}, - packet_parser::parse_commands_from_packet, - Server, -}; - -pub struct Distributor; -#[async_trait] -impl Server for Distributor { - async fn handle( - state: Arc<Mutex<Shared>>, - stream: TcpStream, - _address: SocketAddr, - count: usize, - ) -> Result<(), Box<dyn Error>> { - let bytes = BytesCodec::new().framed(stream); - let mut peer = Peer::new(state.clone(), bytes, count.to_string()).await?; - let mut room_ids = vec![]; - let mut username = String::from("unknown"); - - loop { - tokio::select! { - Some(msg) = peer.rx.recv() => { - peer.bytes.get_mut().write_all(&msg).await?; - } - result = peer.bytes.next() => match result { - Some(Ok(msg)) => { - for msg in parse_commands_from_packet(msg) { - match msg.get(2).unwrap().to_owned() as i32 { - PROPREQ => { - trace!("received property request from client"); - - peer.bytes.get_mut() - .write_all(&create_property_update_as_distributor()).await?; - trace!("sent property update to client"); - } - SESSINIT => { - username = find_property_in_property_list( - &parse_network_property(msg[3..].to_vec()), - VAR_USERNAME, - ).value.clone(); - - trace!("received session initialization from {}", username); - - peer.bytes.get_mut() - .write_all(&create_property_request_as_distributor()).await?; - trace!("sent property request to {}", username); - } - PROPSET => { - trace!("received property set from {}", username); - - peer.bytes.get_mut() - .write_all(&Text { - sender: Config::get().whirlsplash.worldsmaster_username, - content: Config::get().distributor.worldsmaster_greeting, - }.create()).await?; - peer.bytes.get_mut() - .write_all(&create_action()).await?; - trace!("sent text to {}", username); - } - BUDDYLISTUPDATE => { - let buddy = BuddyList::parse(msg.to_vec()); - trace!("received buddy list update from {}: {}", username, buddy.buddy); - peer.bytes.get_mut().write_all(&BuddyList { - ..buddy.clone() - }.create()).await?; - trace!("sent buddy list notify to {}: {}", username, buddy.buddy); - } - ROOMIDRQ => { - let room = RoomIdRequest::parse(msg.to_vec()); - trace!("received room id request from {}: {}", username, &room.room_name); - - let room_id; - if !room_ids.contains(&room.room_name) { - room_ids.push(room.room_name.clone()); - room_id = room_ids.iter().position(|r| r == &room.room_name).unwrap(); - debug!("inserted room: {}", room.room_name); - } else { - let position = room_ids.iter().position(|r| r == &room.room_name).unwrap(); - debug!("found room: {}", room.room_name); - room_id = position; - } - - peer.bytes.get_mut().write_all(&RedirectId { - room_name: room.room_name.clone(), - room_number: room_id as i8, - }.create()).await?; - trace!("sent redirect id to {}: {}", username, room.room_name); - } - SESSEXIT => { - trace!("received session exit from {}", username); break; - } - _ => (), - } - } - } - Some(Err(e)) => { - error!("error while processing message (s): {}", e); break; - } - None => break, - } - } - } - - // Deregister client - trace!("de-registering client"); - { - state.lock().await.peers.remove(&count.to_string()); - } - trace!("de-registered client"); - - Ok(()) - } -} diff --git a/src/server/hub.rs b/src/server/hub.rs deleted file mode 100644 index 99ba600..0000000 --- a/src/server/hub.rs +++ /dev/null @@ -1,163 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -//! The hub functions as a -//! [RoomServer](http://dev.worlds.net/private/GammaDocs/WorldServer.html#AutoServer). -//! -//! The RoomServer is responsible for handling just about every request from the -//! client after they have been redirected to a room (hub). - -use std::{error::Error, net::SocketAddr, sync::Arc}; - -use tokio::{io::AsyncWriteExt, net::TcpStream, sync::Mutex}; -use tokio_stream::StreamExt; -use tokio_util::codec::{BytesCodec, Decoder}; -use whirl_config::Config; - -use crate::server::{ - cmd::{ - commands::{ - action::create_action, - buddy_list::BuddyList, - property::{ - create::{create_property_request_as_hub, create_property_update_as_hub}, - parse::find_property_in_property_list, - }, - subscribe_distance::SubscribeDistance, - subscribe_room::SubscribeRoom, - teleport::Teleport, - text::Text, - }, - constants::*, - extendable::{Creatable, Parsable, ParsableWithArguments}, - }, - interaction::{peer::Peer, shared::Shared}, - net::{constants::VAR_USERNAME, property_parser::parse_network_property}, - packet_parser::parse_commands_from_packet, - Server, -}; - -pub struct Hub; -#[async_trait] -impl Server for Hub { - async fn handle( - state: Arc<Mutex<Shared>>, - stream: TcpStream, - _address: SocketAddr, - count: usize, - ) -> Result<(), Box<dyn Error>> { - let bytes = BytesCodec::new().framed(stream); - let mut peer = Peer::new(state.clone(), bytes, count.to_string()).await?; - // let mut room_ids = vec![]; - let mut username = String::from("unknown"); - - loop { - tokio::select! { - Some(msg) = peer.rx.recv() => { - // dbg!("got peer activity: {:?}", &msg); - peer.bytes.get_mut().write_all(&msg).await?; - } - result = peer.bytes.next() => match result { - Some(Ok(msg)) => { - // dbg!("got some bytes: {:?}", &msg); - for msg in parse_commands_from_packet(msg) { - match msg.get(2).unwrap().to_owned() as i32 { - PROPREQ => { - trace!("received property request from client"); - - peer.bytes.get_mut() - .write_all(&create_property_update_as_hub()).await?; - trace!("sent property update to client"); - } - SESSINIT => { - username = find_property_in_property_list( - &parse_network_property(msg[3..].to_vec()), - VAR_USERNAME, - ).value.clone(); - - trace!("received session initialization from {}", username); - - peer.bytes.get_mut() - .write_all(&create_property_request_as_hub()).await?; - trace!("sent property request to {}", username); - } - PROPSET => { - trace!("received property set from {}", username); - - peer.bytes.get_mut() - .write_all(&Text { - sender: Config::get().whirlsplash.worldsmaster_username, - content: Config::get().distributor.worldsmaster_greeting, - }.create()).await?; - peer.bytes.get_mut() - .write_all(&create_action()).await?; - trace!("sent text to {}", username); - } - BUDDYLISTUPDATE => { - let buddy = BuddyList::parse(msg.to_vec()); - trace!("received buddy list update from {}: {}", username, buddy.buddy); - peer.bytes.get_mut().write_all(&BuddyList { - ..buddy.clone() - }.create()).await?; - trace!("sent buddy list notify to {}: {}", username, buddy.buddy); - } - // TODO: Figure out if this is actually even needed. - // ROOMIDRQ => { - // let room = RoomIdRequest::parse(msg.to_vec()); - // trace!("received room id request from {}: {}", username, room.room_name); - // debug!("{:?}", create_room_id_request(&room.room_name, 0x00)); - // } - SESSEXIT => { - trace!("received session exit from {}", username); break; - } - TEXT => { - let text = Text::parse(msg.to_vec(), &[&username]); - trace!("received text from {}:{}", username, text.content); - - { - state.lock().await.broadcast(&Text { - sender: username.clone(), - content: text.content, - }.create()).await; - } - trace!("broadcasted text to hub"); - } - SUBSCRIB => { - let subscribe_room = SubscribeRoom::parse(msg[3..].to_vec()); - trace!("received subscribe room from {}: {:?}", - username, subscribe_room); - } - SUB_DIST => { - let subscribe_distance = SubscribeDistance::parse(msg[3..].to_vec()); - trace!("received subscribe distance from {}: {:?}", - username, subscribe_distance); - } - TELEPORT => { - let teleport = Teleport::parse(msg[3..].to_vec()); - trace!("received teleport from {}: {:?}", - username, teleport); - } - _ => (), - } - } - } - Some(Err(e)) => { - error!("error while processing message (s): {}", e); break; - } - None => { - debug!("nothing"); break; - }, - } - } - } - - // Deregister client - trace!("de-registering client"); - { - state.lock().await.peers.remove(&count.to_string()); - } - trace!("de-registered client"); - - Ok(()) - } -} diff --git a/src/server/interaction/mod.rs b/src/server/interaction/mod.rs deleted file mode 100644 index c85e09d..0000000 --- a/src/server/interaction/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub mod peer; -pub mod shared; diff --git a/src/server/interaction/peer.rs b/src/server/interaction/peer.rs deleted file mode 100644 index 1d5ed9f..0000000 --- a/src/server/interaction/peer.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use std::sync::Arc; - -use tokio::{ - net::TcpStream, - sync::{mpsc, Mutex}, -}; -use tokio_util::codec::{BytesCodec, Framed}; - -use crate::server::{interaction::shared::Shared, types::Rx}; - -pub struct Peer { - pub bytes: Framed<TcpStream, BytesCodec>, - pub rx: Rx, -} -impl Peer { - pub async fn new( - state: Arc<Mutex<Shared>>, - bytes: Framed<TcpStream, BytesCodec>, - username: String, - ) -> std::io::Result<Peer> { - let (tx, rx) = mpsc::unbounded_channel(); - state.lock().await.peers.insert(username, tx); - - Ok(Peer { - bytes, - rx, - }) - } - - pub async fn _change_username( - self, - state: Arc<Mutex<Shared>>, - username: &str, - new_username: &str, - ) { - // Remove peer from peers - { - state.lock().await.peers.remove(username); - } - - // Add the peer back with the new username - Self::new(state, self.bytes, new_username.to_string()) - .await - .unwrap(); - } -} diff --git a/src/server/interaction/shared.rs b/src/server/interaction/shared.rs deleted file mode 100644 index c9eebbc..0000000 --- a/src/server/interaction/shared.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use std::collections::HashMap; - -use bytes::BytesMut; - -use crate::server::types::Tx; - -pub struct Shared { - pub peers: HashMap<String, Tx>, -} -impl Shared { - pub fn new() -> Self { - Shared { - peers: HashMap::new(), - } - } - - pub async fn broadcast(&mut self, message: &[u8]) { - for peer in self.peers.iter_mut() { - peer.1.send(BytesMut::from(message)).unwrap(); - } - } -} -impl Default for Shared { - fn default() -> Self { Self::new() } -} diff --git a/src/server/mod.rs b/src/server/mod.rs deleted file mode 100644 index 8aad465..0000000 --- a/src/server/mod.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub mod cmd; -mod interaction; -pub mod net; - -pub mod distributor; -pub mod hub; -mod packet_parser; -mod types; - -use std::{error::Error, fmt, net::SocketAddr, sync::Arc}; - -use tokio::{ - net::{TcpListener, TcpStream}, - sync::Mutex, -}; - -use crate::server::interaction::shared::Shared; - -#[derive(Debug)] -pub enum ServerType { - AnonRoomServer, - AnonUserServer, - AutoServer, - RoomServer, - UserServer, -} -// https://stackoverflow.com/a/32712140/14452787 -impl fmt::Display for ServerType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self) } -} - -#[async_trait] -pub trait Server { - async fn listen(address: &str, server_type: ServerType) -> Result<(), Box<dyn Error>> { - let listener = TcpListener::bind(address).await?; - let state = Arc::new(Mutex::new(Shared::new())); - let mut counter = 0; - - info!( - "server of type {} now listening at {}", - server_type.to_string(), - address - ); - - loop { - let (stream, address) = listener.accept().await?; - counter += 1; - let state = Arc::clone(&state); - - trace!("accepted client at {}", address); - - tokio::spawn(async move { - if let Err(e) = Self::handle(state, stream, address, counter).await { - error!("an error occurred: {}", e); - } - }); - } - } - - async fn handle( - state: Arc<Mutex<Shared>>, - stream: TcpStream, - _address: SocketAddr, - count: usize, - ) -> Result<(), Box<dyn Error>>; -} diff --git a/src/server/net/constants.rs b/src/server/net/constants.rs deleted file mode 100644 index 169b461..0000000 --- a/src/server/net/constants.rs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub const VAR_PROTOCOL_VERSION: i32 = 24; -pub const STATECMD: i32 = 2; -pub const MAXCMD: i32 = 255; -pub const CURRENT_ROOM: i32 = 253; -pub const CLIENT: i32 = 1; -pub const CO: i32 = 254; -pub const PO: i32 = 255; -pub const VAR_APPNAME: i32 = 1; -pub const VAR_USERNAME: i32 = 2; -pub const VAR_PROTOCOL: i32 = 3; -pub const VAR_ERROR: i32 = 4; -pub const VAR_CHANNEL: i32 = 5; -pub const VAR_BITMAP: i32 = 5; -pub const VAR_PASSWORD: i32 = 6; -pub const VAR_AVATARS: i32 = 7; -pub const VAR_UPDATETIME: i32 = 8; -pub const VAR_CLIENT: i32 = 9; -pub const VAR_SERIAL: i32 = 10; -pub const VAR_EMAIL: i32 = 11; -pub const VAR_LOGONOFF: i32 = 12; -pub const VAR_DURATION: i32 = 13; -pub const VAR_GUEST: i32 = 14; -pub const VAR_SERVERTYPE: i32 = 15; -pub const VAR_VIZCARD: i32 = 16; -pub const VAR_NEW_PASSWD: i32 = 20; -pub const VAR_PRIV: i32 = 22; -pub const VAR_ASLEEP: i32 = 23; -pub const VAR_EXTERNAL_HTTP_SERVER: i32 = 24; -pub const VAR_SCRIPT_SERVER: i32 = 25; -pub const VAR_SMTP_SERVER: i32 = 26; -pub const VAR_MAIL_DOMAIN: i32 = 27; -pub const VAR_NEW_USERNAME: i32 = 28; -pub const VAR_INTERNAL_HTTP_SERVER: i32 = 29; -pub const VAR_INVENTORY: i32 = 32; -pub const ACK: i32 = 0; -pub const NAK_BAD_USER: i32 = 1; -pub const NAK_MAX_ORDINARY: i32 = 2; -pub const NAK_MAX_PRIORITY: i32 = 3; -pub const NAL_BAD_WORLD: i32 = 4; -pub const NAK_FATAIL: i32 = 5; -pub const NAK_BAD_PROTOCOL: i32 = 6; -pub const NAK_BAD_CLIENTSW: i32 = 7; -pub const NAK_BAD_ROOM: i32 = 8; -pub const NAK_BAD_SERIAL: i32 = 9; -pub const NAK_TAKEN_SERIAL: i32 = 10; -pub const NAK_TAKEN_USER: i32 = 11; -pub const NAK_NO_SUCH_USER: i32 = 12; -pub const NAK_BAD_PASSWORD: i32 = 13; -pub const NAK_BAD_ACCOUNT: i32 = 14; -pub const NAK_NOT_LOGGEDON: i32 = 15; -pub const NAK_BAD_IPADDRESS: i32 = 16; -pub const NAK_LOGGEDON: i32 = 17; -pub const NAK_CRYPT_METHOD: i32 = 18; -pub const NAK_CRYPT_ERROR: i32 = 19; -pub const NAK_SESSIONINIT: i32 = 20; -pub const NAK_ROOM_FULL: i32 = 21; -pub const NAK_SHUTDOWN: i32 = 100; -pub const NAK_WRITE_ERROR: i32 = 101; -pub const NAK_READ_ERROR: i32 = 102; -pub const NAK_UNEXPECTED: i32 = 103; -pub const NAK_CONNECTION: i32 = 104; -pub const NAK_IOSTREAMS: i32 = 105; -pub const NAK_TIMEOUT: i32 = 106; -pub const NAK_UNREACHABLE: i32 = 107; -pub const STATUS_CONNECTED: i32 = 200; -pub const STATUS_DETACHING: i32 = 201; -pub const STATUS_WILLRETRY: i32 = 202; -pub const STATUS_DISCONNECTED: i32 = 203; -pub const STATUS_DEAD: i32 = 204; -pub const STATUS_OFFLINE: i32 = 205; -pub const STATUS_GALAXY_ONLINE: i32 = 206; -pub const STATUS_GALAXY_OFFLINE: i32 = 206; -pub const PROPFLAG_BINARY: i32 = 16; -pub const PROPFLAG_FINGER: i32 = 32; -pub const PROPFLAG_AUTOUPDATE: i32 = 64; -pub const PROPFLAG_DBSTORE: i32 = 128; -pub const PROPACCESS_POSSESS: i32 = 1; -pub const PROPACCESS_PRIVATE: i32 = 2; -pub const SERVER_UNKNOWN: i32 = 0; -pub const USER_SERVER_DB: i32 = 1; -pub const USER_SERVER_ANON: i32 = 2; -pub const ROOM_SERVER_US: i32 = 3; -pub const ROOM_SERVER_ANON: i32 = 4; -pub const PRIV_NONE: i32 = 0; -pub const PRIV_BUILD: i32 = 1; -pub const PRIV_BROADCAST: i32 = 2; -pub const PRIV_PROPERTY: i32 = 4; -pub const PRIV_VIP: i32 = 8; -pub const PRIV_VIP2: i32 = 16; -pub const PRIV_SPECIALGUEST: i32 = 64; diff --git a/src/server/net/converter.rs b/src/server/net/converter.rs deleted file mode 100644 index aa4e8ed..0000000 --- a/src/server/net/converter.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::{BufMut, BytesMut}; - -use crate::server::{ - cmd::constants::PROPUPD, - net::{ - constants::{PROPACCESS_POSSESS, PROPFLAG_DBSTORE}, - structure::NetworkProperty, - }, -}; - -pub fn property_list_to_bytes( - command_id: i32, - obj_id: i32, - mut property_list: Vec<NetworkProperty>, -) -> Vec<u8> { - let mut command = BytesMut::new(); - - // Iterate over all network properties - loop { - // Check if there are any properties left - debug!("props left: {}", property_list.len()); - if property_list.is_empty() { - break; - } - - let property = &property_list[0]; // Property we are currently iterating over - debug!("current prop: {}:{}", property.prop_id, property.value); - - command.put_u8(property.prop_id as u8); // Property ID - - // NOTE: THIS IS SUPER BAD DO NOT DO THIS! But it works! - if command_id == PROPUPD { - command.put_u8(PROPFLAG_DBSTORE as u8); // Flag (s) - command.put_u8(PROPACCESS_POSSESS as u8); // Access - } - - command.put_u8(property.value.len() as u8); // Property UTF-8 Length - command.put_slice(property.value.as_bytes()); // Property UTF-8 - - property_list.reverse(); - property_list.pop(); - property_list.reverse(); - } - - // Convert to vector and insert the header - let mut command_as_vec = command.to_vec(); - - command_as_vec.insert(0, command_id as u8); // Command ID - command_as_vec.insert(0, obj_id as u8); // ObjId - command_as_vec.insert(0, command.len() as u8 + 3); // Data length - - // Return bytes - command_as_vec -} diff --git a/src/server/net/mod.rs b/src/server/net/mod.rs deleted file mode 100644 index afa45c8..0000000 --- a/src/server/net/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub mod constants; -pub mod converter; -pub mod property_parser; -pub mod structure; diff --git a/src/server/net/property_parser.rs b/src/server/net/property_parser.rs deleted file mode 100644 index d6d4ebe..0000000 --- a/src/server/net/property_parser.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use std::str::from_utf8; - -use crate::server::net::structure::NetworkProperty; - -/// Iterate over a network property in the form of bytes and return a list of -/// human-readable properties. -pub fn parse_network_property(mut data: Vec<u8>) -> Vec<NetworkProperty> { - let mut property_list = vec![]; - - // Iterate over all network properties - loop { - // Check if any commands are present - if data.len() <= 2 { - break; - } - debug!("iteration: {:?}", data); - // if data[0] == 0 { - // break; - // } - - let property_length = data[1] + 2; - property_list.push(NetworkProperty { - prop_id: data[0] as i32, - value: from_utf8(&data[2..data[1] as usize + 2]) - .unwrap() - .to_string(), - }); - - // Remove current property from the network property - data = data[property_length as usize..].to_vec(); - } - - // Return the human-readable network property - property_list -} diff --git a/src/server/net/structure.rs b/src/server/net/structure.rs deleted file mode 100644 index 1fb1051..0000000 --- a/src/server/net/structure.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -pub struct NetworkProperty { - pub prop_id: i32, - pub value: String, -} -impl NetworkProperty { - pub fn new() -> Self { NetworkProperty::default() } -} -impl Default for NetworkProperty { - fn default() -> Self { - NetworkProperty { - prop_id: 0, - value: "".to_string(), - } - } -} diff --git a/src/server/packet_parser.rs b/src/server/packet_parser.rs deleted file mode 100644 index c50569d..0000000 --- a/src/server/packet_parser.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::BytesMut; - -/// Read all commands from the given buffer. -/// -/// # Process -/// 1. Get a command from `buffer` based on first byte. -/// 2. Push command to `commands`. -/// 3. Remove command from `buffer`. -/// 4. Iterate and do this for all commands within `buffer`. -pub fn parse_commands_from_packet(mut buffer: BytesMut) -> Vec<BytesMut> { - let mut commands: Vec<BytesMut> = Vec::new(); - debug!("initial buffer: {:?}, length: {}", buffer, buffer.len()); - - let data_length = buffer.get(0).unwrap().to_owned() as usize; - if buffer.len() > data_length { - loop { - debug!("loop: {:?}, length: {}", buffer, buffer.len()); - let command_length = buffer.get(0).unwrap().to_owned() as usize; - commands.push(BytesMut::from(buffer.get(0..command_length).unwrap())); - - // Remove command from buffer - buffer = buffer.split_off(command_length); - - // Check if any more commands are present - if buffer.is_empty() { - break; - } - } - } else { - // There will always be at least one command, push it. - commands.push(BytesMut::from(buffer.get(0..data_length).unwrap())); - } - - commands // Return command (s) -} diff --git a/src/server/types.rs b/src/server/types.rs deleted file mode 100644 index 3d49752..0000000 --- a/src/server/types.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::BytesMut; -use tokio::sync::mpsc; - -pub type Tx = mpsc::UnboundedSender<BytesMut>; -pub type Rx = mpsc::UnboundedReceiver<BytesMut>; |