From f157d081d58bf6d85dabfe873c275efba71d29a5 Mon Sep 17 00:00:00 2001 From: Fuwn Date: Mon, 26 Apr 2021 13:30:51 -0700 Subject: fmt: Rename re_server module to server --- src/lib.rs | 2 +- src/main.rs | 2 +- src/re_server/cmd/commands/action.rs | 20 --- src/re_server/cmd/commands/buddy_list/create.rs | 24 --- src/re_server/cmd/commands/buddy_list/mod.rs | 6 - src/re_server/cmd/commands/buddy_list/parse.rs | 17 --- src/re_server/cmd/commands/buddy_list/structure.rs | 7 - src/re_server/cmd/commands/mod.rs | 12 -- src/re_server/cmd/commands/property/create.rs | 167 --------------------- src/re_server/cmd/commands/property/mod.rs | 5 - src/re_server/cmd/commands/property/parse.rs | 14 -- .../cmd/commands/register_object_id/create.rs | 2 - .../cmd/commands/register_object_id/mod.rs | 4 - src/re_server/cmd/commands/room/create.rs | 34 ----- src/re_server/cmd/commands/room/mod.rs | 5 - src/re_server/cmd/commands/room/parse.rs | 8 - src/re_server/cmd/commands/session/mod.rs | 2 - src/re_server/cmd/commands/session/parse.rs | 2 - src/re_server/cmd/commands/session/structure.rs | 2 - src/re_server/cmd/commands/subscribe/mod.rs | 5 - src/re_server/cmd/commands/subscribe/parse.rs | 21 --- src/re_server/cmd/commands/subscribe/structure.rs | 10 -- src/re_server/cmd/commands/text/create.rs | 31 ---- src/re_server/cmd/commands/text/mod.rs | 6 - src/re_server/cmd/commands/text/parse.rs | 13 -- src/re_server/cmd/commands/text/structure.rs | 7 - src/re_server/cmd/commands/whisper.rs | 2 - src/re_server/cmd/constants.rs | 32 ---- src/re_server/cmd/mod.rs | 8 - src/re_server/cmd/set_parser.rs | 39 ----- src/re_server/cmd/structure.rs | 22 --- src/re_server/distributor.rs | 147 ------------------ src/re_server/hub.rs | 145 ------------------ src/re_server/interaction/mod.rs | 5 - src/re_server/interaction/peer.rs | 49 ------ src/re_server/interaction/shared.rs | 28 ---- src/re_server/mod.rs | 12 -- src/re_server/net/constants.rs | 93 ------------ src/re_server/net/converter.rs | 57 ------- src/re_server/net/mod.rs | 7 - src/re_server/net/property_parser.rs | 38 ----- src/re_server/net/structure.rs | 18 --- src/re_server/packet_parser.rs | 38 ----- src/re_server/server.rs | 60 -------- src/re_server/types.rs | 8 - src/server/cmd/commands/action.rs | 20 +++ src/server/cmd/commands/buddy_list/create.rs | 24 +++ src/server/cmd/commands/buddy_list/mod.rs | 6 + src/server/cmd/commands/buddy_list/parse.rs | 17 +++ src/server/cmd/commands/buddy_list/structure.rs | 7 + src/server/cmd/commands/mod.rs | 12 ++ src/server/cmd/commands/property/create.rs | 167 +++++++++++++++++++++ src/server/cmd/commands/property/mod.rs | 5 + src/server/cmd/commands/property/parse.rs | 14 ++ .../cmd/commands/register_object_id/create.rs | 2 + src/server/cmd/commands/register_object_id/mod.rs | 4 + src/server/cmd/commands/room/create.rs | 34 +++++ src/server/cmd/commands/room/mod.rs | 5 + src/server/cmd/commands/room/parse.rs | 8 + src/server/cmd/commands/session/mod.rs | 2 + src/server/cmd/commands/session/parse.rs | 2 + src/server/cmd/commands/session/structure.rs | 2 + src/server/cmd/commands/subscribe/mod.rs | 5 + src/server/cmd/commands/subscribe/parse.rs | 21 +++ src/server/cmd/commands/subscribe/structure.rs | 10 ++ src/server/cmd/commands/text/create.rs | 31 ++++ src/server/cmd/commands/text/mod.rs | 6 + src/server/cmd/commands/text/parse.rs | 13 ++ src/server/cmd/commands/text/structure.rs | 7 + src/server/cmd/commands/whisper.rs | 2 + src/server/cmd/constants.rs | 32 ++++ src/server/cmd/mod.rs | 8 + src/server/cmd/set_parser.rs | 39 +++++ src/server/cmd/structure.rs | 22 +++ src/server/distributor.rs | 147 ++++++++++++++++++ src/server/hub.rs | 145 ++++++++++++++++++ src/server/interaction/mod.rs | 5 + src/server/interaction/peer.rs | 49 ++++++ src/server/interaction/shared.rs | 28 ++++ src/server/mod.rs | 12 ++ src/server/net/constants.rs | 93 ++++++++++++ src/server/net/converter.rs | 57 +++++++ src/server/net/mod.rs | 7 + src/server/net/property_parser.rs | 38 +++++ src/server/net/structure.rs | 18 +++ src/server/packet_parser.rs | 38 +++++ src/server/server.rs | 60 ++++++++ src/server/types.rs | 8 + 88 files changed, 1234 insertions(+), 1234 deletions(-) delete mode 100644 src/re_server/cmd/commands/action.rs delete mode 100644 src/re_server/cmd/commands/buddy_list/create.rs delete mode 100644 src/re_server/cmd/commands/buddy_list/mod.rs delete mode 100644 src/re_server/cmd/commands/buddy_list/parse.rs delete mode 100644 src/re_server/cmd/commands/buddy_list/structure.rs delete mode 100644 src/re_server/cmd/commands/mod.rs delete mode 100644 src/re_server/cmd/commands/property/create.rs delete mode 100644 src/re_server/cmd/commands/property/mod.rs delete mode 100644 src/re_server/cmd/commands/property/parse.rs delete mode 100644 src/re_server/cmd/commands/register_object_id/create.rs delete mode 100644 src/re_server/cmd/commands/register_object_id/mod.rs delete mode 100644 src/re_server/cmd/commands/room/create.rs delete mode 100644 src/re_server/cmd/commands/room/mod.rs delete mode 100644 src/re_server/cmd/commands/room/parse.rs delete mode 100644 src/re_server/cmd/commands/session/mod.rs delete mode 100644 src/re_server/cmd/commands/session/parse.rs delete mode 100644 src/re_server/cmd/commands/session/structure.rs delete mode 100644 src/re_server/cmd/commands/subscribe/mod.rs delete mode 100644 src/re_server/cmd/commands/subscribe/parse.rs delete mode 100644 src/re_server/cmd/commands/subscribe/structure.rs delete mode 100644 src/re_server/cmd/commands/text/create.rs delete mode 100644 src/re_server/cmd/commands/text/mod.rs delete mode 100644 src/re_server/cmd/commands/text/parse.rs delete mode 100644 src/re_server/cmd/commands/text/structure.rs delete mode 100644 src/re_server/cmd/commands/whisper.rs delete mode 100644 src/re_server/cmd/constants.rs delete mode 100644 src/re_server/cmd/mod.rs delete mode 100644 src/re_server/cmd/set_parser.rs delete mode 100644 src/re_server/cmd/structure.rs delete mode 100644 src/re_server/distributor.rs delete mode 100644 src/re_server/hub.rs delete mode 100644 src/re_server/interaction/mod.rs delete mode 100644 src/re_server/interaction/peer.rs delete mode 100644 src/re_server/interaction/shared.rs delete mode 100644 src/re_server/mod.rs delete mode 100644 src/re_server/net/constants.rs delete mode 100644 src/re_server/net/converter.rs delete mode 100644 src/re_server/net/mod.rs delete mode 100644 src/re_server/net/property_parser.rs delete mode 100644 src/re_server/net/structure.rs delete mode 100644 src/re_server/packet_parser.rs delete mode 100644 src/re_server/server.rs delete mode 100644 src/re_server/types.rs create mode 100644 src/server/cmd/commands/action.rs create mode 100644 src/server/cmd/commands/buddy_list/create.rs create mode 100644 src/server/cmd/commands/buddy_list/mod.rs create mode 100644 src/server/cmd/commands/buddy_list/parse.rs create mode 100644 src/server/cmd/commands/buddy_list/structure.rs create mode 100644 src/server/cmd/commands/mod.rs create mode 100644 src/server/cmd/commands/property/create.rs create mode 100644 src/server/cmd/commands/property/mod.rs create mode 100644 src/server/cmd/commands/property/parse.rs create mode 100644 src/server/cmd/commands/register_object_id/create.rs create mode 100644 src/server/cmd/commands/register_object_id/mod.rs create mode 100644 src/server/cmd/commands/room/create.rs create mode 100644 src/server/cmd/commands/room/mod.rs create mode 100644 src/server/cmd/commands/room/parse.rs create mode 100644 src/server/cmd/commands/session/mod.rs create mode 100644 src/server/cmd/commands/session/parse.rs create mode 100644 src/server/cmd/commands/session/structure.rs create mode 100644 src/server/cmd/commands/subscribe/mod.rs create mode 100644 src/server/cmd/commands/subscribe/parse.rs create mode 100644 src/server/cmd/commands/subscribe/structure.rs create mode 100644 src/server/cmd/commands/text/create.rs create mode 100644 src/server/cmd/commands/text/mod.rs create mode 100644 src/server/cmd/commands/text/parse.rs create mode 100644 src/server/cmd/commands/text/structure.rs create mode 100644 src/server/cmd/commands/whisper.rs create mode 100644 src/server/cmd/constants.rs create mode 100644 src/server/cmd/mod.rs create mode 100644 src/server/cmd/set_parser.rs create mode 100644 src/server/cmd/structure.rs create mode 100644 src/server/distributor.rs create mode 100644 src/server/hub.rs create mode 100644 src/server/interaction/mod.rs create mode 100644 src/server/interaction/peer.rs create mode 100644 src/server/interaction/shared.rs create mode 100644 src/server/mod.rs create mode 100644 src/server/net/constants.rs create mode 100644 src/server/net/converter.rs create mode 100644 src/server/net/mod.rs create mode 100644 src/server/net/property_parser.rs create mode 100644 src/server/net/structure.rs create mode 100644 src/server/packet_parser.rs create mode 100644 src/server/server.rs create mode 100644 src/server/types.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 54ef384..692028c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,5 +11,5 @@ pub mod cli; pub mod config; pub mod db; -pub mod re_server; +pub mod server; pub mod utils; diff --git a/src/main.rs b/src/main.rs index d7b572b..3113704 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ use whirl::{ cli::cli, config, config::get_config, - re_server::{ + server::{ distributor::Distributor, hub::Hub, server::{ diff --git a/src/re_server/cmd/commands/action.rs b/src/re_server/cmd/commands/action.rs deleted file mode 100644 index 99da54f..0000000 --- a/src/re_server/cmd/commands/action.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::{BufMut, BytesMut}; - -pub fn create_action() -> Vec { - 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/re_server/cmd/commands/buddy_list/create.rs b/src/re_server/cmd/commands/buddy_list/create.rs deleted file mode 100644 index e201cbb..0000000 --- a/src/re_server/cmd/commands/buddy_list/create.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::{BufMut, BytesMut}; - -use crate::re_server::cmd::{commands::buddy_list::structure::Buddy, constants::BUDDYLISTNOTIFY}; - -pub fn create_buddy_list_notify(buddy: &Buddy) -> Vec { - let mut command = BytesMut::new(); - - // Header - command.put_u8(0x01); // ObjId - command.put_u8(BUDDYLISTNOTIFY as u8); // Type - - // Content - command.put_u8(buddy.buddy.len() as u8); // Buddy (name) length - command.put_slice(buddy.buddy.as_bytes()); // Buddy (name) - command.put_u8(buddy.add); // "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/re_server/cmd/commands/buddy_list/mod.rs b/src/re_server/cmd/commands/buddy_list/mod.rs deleted file mode 100644 index 14440dc..0000000 --- a/src/re_server/cmd/commands/buddy_list/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod create; -pub mod parse; -pub mod structure; diff --git a/src/re_server/cmd/commands/buddy_list/parse.rs b/src/re_server/cmd/commands/buddy_list/parse.rs deleted file mode 100644 index 6705aaa..0000000 --- a/src/re_server/cmd/commands/buddy_list/parse.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use std::str::from_utf8; - -use crate::re_server::cmd::commands::buddy_list::structure::Buddy; - -pub fn parse_buddy_list_update(data: Vec) -> Buddy { - Buddy { - buddy: from_utf8(&data[4..data[0] as usize - 1]) - .unwrap() - .to_string(), - - // Get the last byte - add: data[data[0] as usize - 1], - } -} diff --git a/src/re_server/cmd/commands/buddy_list/structure.rs b/src/re_server/cmd/commands/buddy_list/structure.rs deleted file mode 100644 index 5da24d5..0000000 --- a/src/re_server/cmd/commands/buddy_list/structure.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub struct Buddy { - pub buddy: String, - pub add: u8, -} diff --git a/src/re_server/cmd/commands/mod.rs b/src/re_server/cmd/commands/mod.rs deleted file mode 100644 index b484e2f..0000000 --- a/src/re_server/cmd/commands/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod action; -pub mod buddy_list; -pub mod property; -pub mod room; -pub mod session; -pub mod subscribe; -pub mod text; -pub mod whisper; -// pub mod register_object_id; // TODO: Implement. diff --git a/src/re_server/cmd/commands/property/create.rs b/src/re_server/cmd/commands/property/create.rs deleted file mode 100644 index 9ea1dec..0000000 --- a/src/re_server/cmd/commands/property/create.rs +++ /dev/null @@ -1,167 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use crate::{ - config::get_config, - re_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 { - 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: get_config().unwrap().worldsmaster_username, - }, - ], - ) -} - -pub fn create_property_update_as_hub() -> Vec { - 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: get_config().unwrap().worldsmaster_username, - }, - ], - ) -} - -pub fn create_property_request_as_distributor() -> Vec { - property_list_to_bytes( - SESSINIT as i32, - 0x01, - vec![ - NetworkProperty { - prop_id: VAR_ERROR, - value: "0".to_string(), - }, - NetworkProperty { - prop_id: VAR_APPNAME, - value: get_config().unwrap().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 { - 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/re_server/cmd/commands/property/mod.rs b/src/re_server/cmd/commands/property/mod.rs deleted file mode 100644 index 0bea58f..0000000 --- a/src/re_server/cmd/commands/property/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod create; -pub mod parse; diff --git a/src/re_server/cmd/commands/property/parse.rs b/src/re_server/cmd/commands/property/parse.rs deleted file mode 100644 index 50bde06..0000000 --- a/src/re_server/cmd/commands/property/parse.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use crate::re_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/re_server/cmd/commands/register_object_id/create.rs b/src/re_server/cmd/commands/register_object_id/create.rs deleted file mode 100644 index 858d572..0000000 --- a/src/re_server/cmd/commands/register_object_id/create.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/re_server/cmd/commands/register_object_id/mod.rs b/src/re_server/cmd/commands/register_object_id/mod.rs deleted file mode 100644 index 08317e1..0000000 --- a/src/re_server/cmd/commands/register_object_id/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod create; diff --git a/src/re_server/cmd/commands/room/create.rs b/src/re_server/cmd/commands/room/create.rs deleted file mode 100644 index 8cfb960..0000000 --- a/src/re_server/cmd/commands/room/create.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::{BufMut, BytesMut}; - -use crate::{config::get_config, re_server::cmd::constants::REDIRID}; - -pub fn create_room_id_request(room: &str, room_id: u8) -> Vec { - let mut command = BytesMut::new(); - - // Header - command.put_u8(0x01); // ObjId - command.put_u8(REDIRID as u8); // Type - - // Content - command.put_u8(room.len() as u8); // Room name length - command.put_slice(room.as_bytes()); // Room name - // command.put_u8(0x00); // Unimplemented byte (?) - // command.put_u8(room_id); // Room ID - command.put_u16(room_id as u16); // Room ID - - // IP - for byte in "0.0.0.0".split('.') { - command.put_u8(byte.parse::().unwrap()); - } - command.put_u16(get_config().unwrap().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/re_server/cmd/commands/room/mod.rs b/src/re_server/cmd/commands/room/mod.rs deleted file mode 100644 index 0bea58f..0000000 --- a/src/re_server/cmd/commands/room/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod create; -pub mod parse; diff --git a/src/re_server/cmd/commands/room/parse.rs b/src/re_server/cmd/commands/room/parse.rs deleted file mode 100644 index 70bd0a8..0000000 --- a/src/re_server/cmd/commands/room/parse.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use std::str::from_utf8; - -pub fn parse_room_id_request(data: Vec) -> String { - from_utf8(&data[4..data[0] as usize]).unwrap().to_string() -} diff --git a/src/re_server/cmd/commands/session/mod.rs b/src/re_server/cmd/commands/session/mod.rs deleted file mode 100644 index 858d572..0000000 --- a/src/re_server/cmd/commands/session/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/re_server/cmd/commands/session/parse.rs b/src/re_server/cmd/commands/session/parse.rs deleted file mode 100644 index 858d572..0000000 --- a/src/re_server/cmd/commands/session/parse.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/re_server/cmd/commands/session/structure.rs b/src/re_server/cmd/commands/session/structure.rs deleted file mode 100644 index 858d572..0000000 --- a/src/re_server/cmd/commands/session/structure.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/re_server/cmd/commands/subscribe/mod.rs b/src/re_server/cmd/commands/subscribe/mod.rs deleted file mode 100644 index d7fec55..0000000 --- a/src/re_server/cmd/commands/subscribe/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -mod parse; -mod structure; diff --git a/src/re_server/cmd/commands/subscribe/parse.rs b/src/re_server/cmd/commands/subscribe/parse.rs deleted file mode 100644 index 657b4ba..0000000 --- a/src/re_server/cmd/commands/subscribe/parse.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use byteorder::{BigEndian, ReadBytesExt}; -use bytes::{Buf, BytesMut}; - -use crate::re_server::cmd::commands::subscribe::structure::SubscribeRoom; - -/// TODO: The functionality of this function has not been tested... TEST IT! -pub fn parse_subscribe_room(data: Vec) -> SubscribeRoom { - // https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8 - let mut data = BytesMut::from(data.as_slice()).reader(); - - SubscribeRoom { - room_number: data.read_i16::().unwrap(), - distance: data.read_i16::().unwrap(), - x: data.read_i16::().unwrap(), - y: data.read_i16::().unwrap(), - z: data.read_i16::().unwrap(), - } -} diff --git a/src/re_server/cmd/commands/subscribe/structure.rs b/src/re_server/cmd/commands/subscribe/structure.rs deleted file mode 100644 index 6142aaa..0000000 --- a/src/re_server/cmd/commands/subscribe/structure.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub struct SubscribeRoom { - pub room_number: i16, - pub distance: i16, - pub x: i16, - pub y: i16, - pub z: i16, -} diff --git a/src/re_server/cmd/commands/text/create.rs b/src/re_server/cmd/commands/text/create.rs deleted file mode 100644 index 6e1a5a8..0000000 --- a/src/re_server/cmd/commands/text/create.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::{BufMut, BytesMut}; - -use crate::re_server::cmd::{commands::text::structure::Text, constants::TEXT}; - -pub fn create_text(text: Text) -> Vec { - let mut command = BytesMut::new(); - - // Header - command.put_u8(0x01); - command.put_u8(TEXT as u8); - - // Content - // The fourth and fifth elements are presumed to be interpreted as a short by - // the client, however, usernames aren't (?) allowed to be long enough that - // they reach a number high enough to be converted to a short. - command.put_u8(0x00); - command.put_u8(text.sender.len() as u8); - command.put_slice(text.sender.as_bytes()); - command.put_u8(text.content.len() as u8); - command.put_slice(text.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 -} diff --git a/src/re_server/cmd/commands/text/mod.rs b/src/re_server/cmd/commands/text/mod.rs deleted file mode 100644 index 14440dc..0000000 --- a/src/re_server/cmd/commands/text/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod create; -pub mod parse; -pub mod structure; diff --git a/src/re_server/cmd/commands/text/parse.rs b/src/re_server/cmd/commands/text/parse.rs deleted file mode 100644 index 078c19f..0000000 --- a/src/re_server/cmd/commands/text/parse.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use std::str::from_utf8; - -use crate::re_server::cmd::commands::text::structure::Text; - -pub fn parse_text(data: Vec, username: &str) -> Text { - Text { - sender: username.to_string(), - content: from_utf8(&data[6..]).unwrap().to_string(), - } -} diff --git a/src/re_server/cmd/commands/text/structure.rs b/src/re_server/cmd/commands/text/structure.rs deleted file mode 100644 index eaeef38..0000000 --- a/src/re_server/cmd/commands/text/structure.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub struct Text { - pub sender: String, - pub content: String, -} diff --git a/src/re_server/cmd/commands/whisper.rs b/src/re_server/cmd/commands/whisper.rs deleted file mode 100644 index 858d572..0000000 --- a/src/re_server/cmd/commands/whisper.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/re_server/cmd/constants.rs b/src/re_server/cmd/constants.rs deleted file mode 100644 index 0db4143..0000000 --- a/src/re_server/cmd/constants.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// 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/re_server/cmd/mod.rs b/src/re_server/cmd/mod.rs deleted file mode 100644 index c01f582..0000000 --- a/src/re_server/cmd/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod commands; - -pub mod constants; -mod set_parser; -mod structure; diff --git a/src/re_server/cmd/set_parser.rs b/src/re_server/cmd/set_parser.rs deleted file mode 100644 index 94ea51e..0000000 --- a/src/re_server/cmd/set_parser.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use crate::re_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) -> Vec { - 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/re_server/cmd/structure.rs b/src/re_server/cmd/structure.rs deleted file mode 100644 index ea6bc0c..0000000 --- a/src/re_server/cmd/structure.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub struct Command { - pub length: i32, - pub obj_id: i32, - pub id: i32, - pub body: Vec, -} -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/re_server/distributor.rs b/src/re_server/distributor.rs deleted file mode 100644 index d952fb7..0000000 --- a/src/re_server/distributor.rs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// 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 crate::{ - config::get_config, - re_server::{ - cmd::{ - commands::{ - action::create_action, - buddy_list::{create::create_buddy_list_notify, parse::parse_buddy_list_update}, - property::{ - create::{create_property_request_as_distributor, create_property_update_as_distributor}, - parse::find_property_in_property_list, - }, - room::{create::create_room_id_request, parse::parse_room_id_request}, - text::{create::create_text, structure::Text}, - }, - constants::*, - }, - interaction::{peer::Peer, shared::Shared}, - net::{constants::VAR_USERNAME, property_parser::parse_network_property}, - packet_parser::parse_commands_from_packet, - server::Server, - }, -}; - -pub struct Distributor; -#[async_trait::async_trait] -impl Server for Distributor { - async fn handle( - state: Arc>, - stream: TcpStream, - _address: SocketAddr, - count: usize, - ) -> Result<(), Box> { - 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(&create_text(Text { - sender: get_config()?.worldsmaster_username, - content: get_config()?.worldsmaster_greeting, - })).await?; - peer.bytes.get_mut() - .write_all(&create_action()).await?; - trace!("sent text to {}", username); - } - BUDDYLISTUPDATE => { - let buddy = parse_buddy_list_update(msg.to_vec()); - trace!("received buddy list update from {}: {}", username, buddy.buddy); - peer.bytes.get_mut() - .write_all(&create_buddy_list_notify(&buddy)).await?; - trace!("sent buddy list notify to {}: {}", username, buddy.buddy); - } - ROOMIDRQ => { - let room = parse_room_id_request(msg.to_vec()); - trace!("received room id request from {}: {}", username, &room); - - let room_id; - if !room_ids.contains(&room) { - room_ids.push(room.clone()); - room_id = room_ids.iter().position(|r| r == &room).unwrap(); - debug!("inserted room: {}", room); - } else { - let position = room_ids.iter().position(|r| r == &room).unwrap(); - debug!("found room: {}", room); - room_id = position; - } - - peer.bytes.get_mut() - .write_all(&create_room_id_request(&room, room_id as u8)).await?; - trace!("sent room id redirect to {}: {}", username, room); - } - 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/re_server/hub.rs b/src/re_server/hub.rs deleted file mode 100644 index a9c30bd..0000000 --- a/src/re_server/hub.rs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// 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 crate::{ - config::get_config, - re_server::{ - cmd::{ - commands::{ - action::create_action, - buddy_list::{create::create_buddy_list_notify, parse::parse_buddy_list_update}, - property::{ - create::{create_property_request_as_hub, create_property_update_as_hub}, - parse::find_property_in_property_list, - }, - room::{create::create_room_id_request, parse::parse_room_id_request}, - text::{create::create_text, parse::parse_text, structure::Text}, - }, - constants::*, - }, - interaction::{peer::Peer, shared::Shared}, - net::{constants::VAR_USERNAME, property_parser::parse_network_property}, - packet_parser::parse_commands_from_packet, - server::Server, - }, -}; - -pub struct Hub; -#[async_trait::async_trait] -impl Server for Hub { - async fn handle( - state: Arc>, - stream: TcpStream, - _address: SocketAddr, - count: usize, - ) -> Result<(), Box> { - 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(&create_text(Text { - sender: get_config()?.worldsmaster_username, - content: get_config()?.worldsmaster_greeting, - })).await?; - peer.bytes.get_mut() - .write_all(&create_action()).await?; - trace!("sent text to {}", username); - } - BUDDYLISTUPDATE => { - let buddy = parse_buddy_list_update(msg.to_vec()); - trace!("received buddy list update from {}: {}", username, buddy.buddy); - peer.bytes.get_mut() - .write_all(&create_buddy_list_notify(&buddy)).await?; - trace!("sent buddy list notify to {}: {}", username, buddy.buddy); - } - ROOMIDRQ => { - let room = parse_room_id_request(msg.to_vec()); - trace!("received room id request from {}: {}", username, room); - debug!("{:?}", create_room_id_request(&room, 0x04)); - } - SESSEXIT => { - trace!("received session exit from {}", username); break; - } - TEXT => { - let text = parse_text(msg.to_vec(), &username); - trace!("received text from {}:{}", username, text.content); - - { - state.lock().await.broadcast(&create_text(Text { - sender: username.clone(), - content: text.content, - })).await; - } - trace!("broadcasted text to hub"); - } - _ => (), - } - } - } - 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/re_server/interaction/mod.rs b/src/re_server/interaction/mod.rs deleted file mode 100644 index 4f0f38b..0000000 --- a/src/re_server/interaction/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod peer; -pub mod shared; diff --git a/src/re_server/interaction/peer.rs b/src/re_server/interaction/peer.rs deleted file mode 100644 index 898c5c8..0000000 --- a/src/re_server/interaction/peer.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// 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::re_server::{interaction::shared::Shared, types::Rx}; - -pub struct Peer { - pub bytes: Framed, - pub rx: Rx, -} -impl Peer { - pub async fn new( - state: Arc>, - bytes: Framed, - username: String, - ) -> std::io::Result { - 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>, - 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/re_server/interaction/shared.rs b/src/re_server/interaction/shared.rs deleted file mode 100644 index 9af6952..0000000 --- a/src/re_server/interaction/shared.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use std::collections::HashMap; - -use bytes::BytesMut; - -use crate::re_server::types::Tx; - -pub struct Shared { - pub peers: HashMap, -} -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/re_server/mod.rs b/src/re_server/mod.rs deleted file mode 100644 index 8cd477d..0000000 --- a/src/re_server/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod cmd; -mod interaction; -pub mod net; - -pub mod distributor; -pub mod hub; -mod packet_parser; -pub mod server; -mod types; diff --git a/src/re_server/net/constants.rs b/src/re_server/net/constants.rs deleted file mode 100644 index 04d94a9..0000000 --- a/src/re_server/net/constants.rs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// 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/re_server/net/converter.rs b/src/re_server/net/converter.rs deleted file mode 100644 index 7087bc1..0000000 --- a/src/re_server/net/converter.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::{BufMut, BytesMut}; - -use crate::re_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, -) -> Vec { - 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/re_server/net/mod.rs b/src/re_server/net/mod.rs deleted file mode 100644 index c88ab7f..0000000 --- a/src/re_server/net/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -pub mod constants; -pub mod converter; -pub mod property_parser; -pub mod structure; diff --git a/src/re_server/net/property_parser.rs b/src/re_server/net/property_parser.rs deleted file mode 100644 index ff03643..0000000 --- a/src/re_server/net/property_parser.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use std::str::from_utf8; - -use crate::re_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) -> Vec { - 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/re_server/net/structure.rs b/src/re_server/net/structure.rs deleted file mode 100644 index 0128c0e..0000000 --- a/src/re_server/net/structure.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// 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/re_server/packet_parser.rs b/src/re_server/packet_parser.rs deleted file mode 100644 index d8fd93d..0000000 --- a/src/re_server/packet_parser.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// 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 { - let mut commands: Vec = 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/re_server/server.rs b/src/re_server/server.rs deleted file mode 100644 index 1e64476..0000000 --- a/src/re_server/server.rs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use std::{error::Error, fmt, net::SocketAddr, sync::Arc}; - -use tokio::{ - net::{TcpListener, TcpStream}, - sync::Mutex, -}; - -use crate::re_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::async_trait] -pub trait Server { - async fn listen(address: &str, server_type: ServerType) -> Result<(), Box> { - 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>, - stream: TcpStream, - _address: SocketAddr, - count: usize, - ) -> Result<(), Box>; -} diff --git a/src/re_server/types.rs b/src/re_server/types.rs deleted file mode 100644 index 8330875..0000000 --- a/src/re_server/types.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyleft 2021-2021 Whirlsplash -// SPDX-License-Identifier: GPL-3.0-only - -use bytes::BytesMut; -use tokio::sync::mpsc; - -pub type Tx = mpsc::UnboundedSender; -pub type Rx = mpsc::UnboundedReceiver; diff --git a/src/server/cmd/commands/action.rs b/src/server/cmd/commands/action.rs new file mode 100644 index 0000000..99da54f --- /dev/null +++ b/src/server/cmd/commands/action.rs @@ -0,0 +1,20 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use bytes::{BufMut, BytesMut}; + +pub fn create_action() -> Vec { + 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/create.rs b/src/server/cmd/commands/buddy_list/create.rs new file mode 100644 index 0000000..bc4b10a --- /dev/null +++ b/src/server/cmd/commands/buddy_list/create.rs @@ -0,0 +1,24 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use bytes::{BufMut, BytesMut}; + +use crate::server::cmd::{commands::buddy_list::structure::Buddy, constants::BUDDYLISTNOTIFY}; + +pub fn create_buddy_list_notify(buddy: &Buddy) -> Vec { + let mut command = BytesMut::new(); + + // Header + command.put_u8(0x01); // ObjId + command.put_u8(BUDDYLISTNOTIFY as u8); // Type + + // Content + command.put_u8(buddy.buddy.len() as u8); // Buddy (name) length + command.put_slice(buddy.buddy.as_bytes()); // Buddy (name) + command.put_u8(buddy.add); // "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/buddy_list/mod.rs b/src/server/cmd/commands/buddy_list/mod.rs new file mode 100644 index 0000000..14440dc --- /dev/null +++ b/src/server/cmd/commands/buddy_list/mod.rs @@ -0,0 +1,6 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub mod create; +pub mod parse; +pub mod structure; diff --git a/src/server/cmd/commands/buddy_list/parse.rs b/src/server/cmd/commands/buddy_list/parse.rs new file mode 100644 index 0000000..163052c --- /dev/null +++ b/src/server/cmd/commands/buddy_list/parse.rs @@ -0,0 +1,17 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use std::str::from_utf8; + +use crate::server::cmd::commands::buddy_list::structure::Buddy; + +pub fn parse_buddy_list_update(data: Vec) -> Buddy { + Buddy { + buddy: from_utf8(&data[4..data[0] as usize - 1]) + .unwrap() + .to_string(), + + // Get the last byte + add: data[data[0] as usize - 1], + } +} diff --git a/src/server/cmd/commands/buddy_list/structure.rs b/src/server/cmd/commands/buddy_list/structure.rs new file mode 100644 index 0000000..5da24d5 --- /dev/null +++ b/src/server/cmd/commands/buddy_list/structure.rs @@ -0,0 +1,7 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub struct Buddy { + pub buddy: String, + pub add: u8, +} diff --git a/src/server/cmd/commands/mod.rs b/src/server/cmd/commands/mod.rs new file mode 100644 index 0000000..b484e2f --- /dev/null +++ b/src/server/cmd/commands/mod.rs @@ -0,0 +1,12 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub mod action; +pub mod buddy_list; +pub mod property; +pub mod room; +pub mod session; +pub mod subscribe; +pub mod text; +pub mod whisper; +// pub mod register_object_id; // TODO: Implement. diff --git a/src/server/cmd/commands/property/create.rs b/src/server/cmd/commands/property/create.rs new file mode 100644 index 0000000..8521a8e --- /dev/null +++ b/src/server/cmd/commands/property/create.rs @@ -0,0 +1,167 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use crate::{ + config::get_config, + 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 { + 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: get_config().unwrap().worldsmaster_username, + }, + ], + ) +} + +pub fn create_property_update_as_hub() -> Vec { + 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: get_config().unwrap().worldsmaster_username, + }, + ], + ) +} + +pub fn create_property_request_as_distributor() -> Vec { + property_list_to_bytes( + SESSINIT as i32, + 0x01, + vec![ + NetworkProperty { + prop_id: VAR_ERROR, + value: "0".to_string(), + }, + NetworkProperty { + prop_id: VAR_APPNAME, + value: get_config().unwrap().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 { + 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 new file mode 100644 index 0000000..0bea58f --- /dev/null +++ b/src/server/cmd/commands/property/mod.rs @@ -0,0 +1,5 @@ +// Copyleft 2021-2021 Whirlsplash +// 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 new file mode 100644 index 0000000..1d48db0 --- /dev/null +++ b/src/server/cmd/commands/property/parse.rs @@ -0,0 +1,14 @@ +// Copyleft 2021-2021 Whirlsplash +// 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/register_object_id/create.rs b/src/server/cmd/commands/register_object_id/create.rs new file mode 100644 index 0000000..858d572 --- /dev/null +++ b/src/server/cmd/commands/register_object_id/create.rs @@ -0,0 +1,2 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/server/cmd/commands/register_object_id/mod.rs b/src/server/cmd/commands/register_object_id/mod.rs new file mode 100644 index 0000000..08317e1 --- /dev/null +++ b/src/server/cmd/commands/register_object_id/mod.rs @@ -0,0 +1,4 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub mod create; diff --git a/src/server/cmd/commands/room/create.rs b/src/server/cmd/commands/room/create.rs new file mode 100644 index 0000000..a195936 --- /dev/null +++ b/src/server/cmd/commands/room/create.rs @@ -0,0 +1,34 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use bytes::{BufMut, BytesMut}; + +use crate::{config::get_config, server::cmd::constants::REDIRID}; + +pub fn create_room_id_request(room: &str, room_id: u8) -> Vec { + let mut command = BytesMut::new(); + + // Header + command.put_u8(0x01); // ObjId + command.put_u8(REDIRID as u8); // Type + + // Content + command.put_u8(room.len() as u8); // Room name length + command.put_slice(room.as_bytes()); // Room name + // command.put_u8(0x00); // Unimplemented byte (?) + // command.put_u8(room_id); // Room ID + command.put_u16(room_id as u16); // Room ID + + // IP + for byte in "0.0.0.0".split('.') { + command.put_u8(byte.parse::().unwrap()); + } + command.put_u16(get_config().unwrap().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/mod.rs b/src/server/cmd/commands/room/mod.rs new file mode 100644 index 0000000..0bea58f --- /dev/null +++ b/src/server/cmd/commands/room/mod.rs @@ -0,0 +1,5 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub mod create; +pub mod parse; diff --git a/src/server/cmd/commands/room/parse.rs b/src/server/cmd/commands/room/parse.rs new file mode 100644 index 0000000..70bd0a8 --- /dev/null +++ b/src/server/cmd/commands/room/parse.rs @@ -0,0 +1,8 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use std::str::from_utf8; + +pub fn parse_room_id_request(data: Vec) -> String { + from_utf8(&data[4..data[0] as usize]).unwrap().to_string() +} diff --git a/src/server/cmd/commands/session/mod.rs b/src/server/cmd/commands/session/mod.rs new file mode 100644 index 0000000..858d572 --- /dev/null +++ b/src/server/cmd/commands/session/mod.rs @@ -0,0 +1,2 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/server/cmd/commands/session/parse.rs b/src/server/cmd/commands/session/parse.rs new file mode 100644 index 0000000..858d572 --- /dev/null +++ b/src/server/cmd/commands/session/parse.rs @@ -0,0 +1,2 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/server/cmd/commands/session/structure.rs b/src/server/cmd/commands/session/structure.rs new file mode 100644 index 0000000..858d572 --- /dev/null +++ b/src/server/cmd/commands/session/structure.rs @@ -0,0 +1,2 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/server/cmd/commands/subscribe/mod.rs b/src/server/cmd/commands/subscribe/mod.rs new file mode 100644 index 0000000..d7fec55 --- /dev/null +++ b/src/server/cmd/commands/subscribe/mod.rs @@ -0,0 +1,5 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +mod parse; +mod structure; diff --git a/src/server/cmd/commands/subscribe/parse.rs b/src/server/cmd/commands/subscribe/parse.rs new file mode 100644 index 0000000..2a17cb2 --- /dev/null +++ b/src/server/cmd/commands/subscribe/parse.rs @@ -0,0 +1,21 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use byteorder::{BigEndian, ReadBytesExt}; +use bytes::{Buf, BytesMut}; + +use crate::server::cmd::commands::subscribe::structure::SubscribeRoom; + +/// TODO: The functionality of this function has not been tested... TEST IT! +pub fn parse_subscribe_room(data: Vec) -> SubscribeRoom { + // https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8 + let mut data = BytesMut::from(data.as_slice()).reader(); + + SubscribeRoom { + room_number: data.read_i16::().unwrap(), + distance: data.read_i16::().unwrap(), + x: data.read_i16::().unwrap(), + y: data.read_i16::().unwrap(), + z: data.read_i16::().unwrap(), + } +} diff --git a/src/server/cmd/commands/subscribe/structure.rs b/src/server/cmd/commands/subscribe/structure.rs new file mode 100644 index 0000000..6142aaa --- /dev/null +++ b/src/server/cmd/commands/subscribe/structure.rs @@ -0,0 +1,10 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub struct SubscribeRoom { + pub room_number: i16, + pub distance: i16, + pub x: i16, + pub y: i16, + pub z: i16, +} diff --git a/src/server/cmd/commands/text/create.rs b/src/server/cmd/commands/text/create.rs new file mode 100644 index 0000000..879f9bd --- /dev/null +++ b/src/server/cmd/commands/text/create.rs @@ -0,0 +1,31 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use bytes::{BufMut, BytesMut}; + +use crate::server::cmd::{commands::text::structure::Text, constants::TEXT}; + +pub fn create_text(text: Text) -> Vec { + let mut command = BytesMut::new(); + + // Header + command.put_u8(0x01); + command.put_u8(TEXT as u8); + + // Content + // The fourth and fifth elements are presumed to be interpreted as a short by + // the client, however, usernames aren't (?) allowed to be long enough that + // they reach a number high enough to be converted to a short. + command.put_u8(0x00); + command.put_u8(text.sender.len() as u8); + command.put_slice(text.sender.as_bytes()); + command.put_u8(text.content.len() as u8); + command.put_slice(text.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 +} diff --git a/src/server/cmd/commands/text/mod.rs b/src/server/cmd/commands/text/mod.rs new file mode 100644 index 0000000..14440dc --- /dev/null +++ b/src/server/cmd/commands/text/mod.rs @@ -0,0 +1,6 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub mod create; +pub mod parse; +pub mod structure; diff --git a/src/server/cmd/commands/text/parse.rs b/src/server/cmd/commands/text/parse.rs new file mode 100644 index 0000000..a7f66d0 --- /dev/null +++ b/src/server/cmd/commands/text/parse.rs @@ -0,0 +1,13 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use std::str::from_utf8; + +use crate::server::cmd::commands::text::structure::Text; + +pub fn parse_text(data: Vec, username: &str) -> Text { + Text { + sender: username.to_string(), + content: from_utf8(&data[6..]).unwrap().to_string(), + } +} diff --git a/src/server/cmd/commands/text/structure.rs b/src/server/cmd/commands/text/structure.rs new file mode 100644 index 0000000..eaeef38 --- /dev/null +++ b/src/server/cmd/commands/text/structure.rs @@ -0,0 +1,7 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub struct Text { + pub sender: String, + pub content: String, +} diff --git a/src/server/cmd/commands/whisper.rs b/src/server/cmd/commands/whisper.rs new file mode 100644 index 0000000..858d572 --- /dev/null +++ b/src/server/cmd/commands/whisper.rs @@ -0,0 +1,2 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only diff --git a/src/server/cmd/constants.rs b/src/server/cmd/constants.rs new file mode 100644 index 0000000..0db4143 --- /dev/null +++ b/src/server/cmd/constants.rs @@ -0,0 +1,32 @@ +// Copyleft 2021-2021 Whirlsplash +// 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/mod.rs b/src/server/cmd/mod.rs new file mode 100644 index 0000000..c01f582 --- /dev/null +++ b/src/server/cmd/mod.rs @@ -0,0 +1,8 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub mod commands; + +pub mod constants; +mod set_parser; +mod structure; diff --git a/src/server/cmd/set_parser.rs b/src/server/cmd/set_parser.rs new file mode 100644 index 0000000..c998dcc --- /dev/null +++ b/src/server/cmd/set_parser.rs @@ -0,0 +1,39 @@ +// Copyleft 2021-2021 Whirlsplash +// 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) -> Vec { + 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 new file mode 100644 index 0000000..ea6bc0c --- /dev/null +++ b/src/server/cmd/structure.rs @@ -0,0 +1,22 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub struct Command { + pub length: i32, + pub obj_id: i32, + pub id: i32, + pub body: Vec, +} +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 new file mode 100644 index 0000000..4e7a694 --- /dev/null +++ b/src/server/distributor.rs @@ -0,0 +1,147 @@ +// Copyleft 2021-2021 Whirlsplash +// 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 crate::{ + config::get_config, + server::{ + cmd::{ + commands::{ + action::create_action, + buddy_list::{create::create_buddy_list_notify, parse::parse_buddy_list_update}, + property::{ + create::{create_property_request_as_distributor, create_property_update_as_distributor}, + parse::find_property_in_property_list, + }, + room::{create::create_room_id_request, parse::parse_room_id_request}, + text::{create::create_text, structure::Text}, + }, + constants::*, + }, + interaction::{peer::Peer, shared::Shared}, + net::{constants::VAR_USERNAME, property_parser::parse_network_property}, + packet_parser::parse_commands_from_packet, + server::Server, + }, +}; + +pub struct Distributor; +#[async_trait::async_trait] +impl Server for Distributor { + async fn handle( + state: Arc>, + stream: TcpStream, + _address: SocketAddr, + count: usize, + ) -> Result<(), Box> { + 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(&create_text(Text { + sender: get_config()?.worldsmaster_username, + content: get_config()?.worldsmaster_greeting, + })).await?; + peer.bytes.get_mut() + .write_all(&create_action()).await?; + trace!("sent text to {}", username); + } + BUDDYLISTUPDATE => { + let buddy = parse_buddy_list_update(msg.to_vec()); + trace!("received buddy list update from {}: {}", username, buddy.buddy); + peer.bytes.get_mut() + .write_all(&create_buddy_list_notify(&buddy)).await?; + trace!("sent buddy list notify to {}: {}", username, buddy.buddy); + } + ROOMIDRQ => { + let room = parse_room_id_request(msg.to_vec()); + trace!("received room id request from {}: {}", username, &room); + + let room_id; + if !room_ids.contains(&room) { + room_ids.push(room.clone()); + room_id = room_ids.iter().position(|r| r == &room).unwrap(); + debug!("inserted room: {}", room); + } else { + let position = room_ids.iter().position(|r| r == &room).unwrap(); + debug!("found room: {}", room); + room_id = position; + } + + peer.bytes.get_mut() + .write_all(&create_room_id_request(&room, room_id as u8)).await?; + trace!("sent room id redirect to {}: {}", username, room); + } + 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 new file mode 100644 index 0000000..6a1480f --- /dev/null +++ b/src/server/hub.rs @@ -0,0 +1,145 @@ +// Copyleft 2021-2021 Whirlsplash +// 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 crate::{ + config::get_config, + server::{ + cmd::{ + commands::{ + action::create_action, + buddy_list::{create::create_buddy_list_notify, parse::parse_buddy_list_update}, + property::{ + create::{create_property_request_as_hub, create_property_update_as_hub}, + parse::find_property_in_property_list, + }, + room::{create::create_room_id_request, parse::parse_room_id_request}, + text::{create::create_text, parse::parse_text, structure::Text}, + }, + constants::*, + }, + interaction::{peer::Peer, shared::Shared}, + net::{constants::VAR_USERNAME, property_parser::parse_network_property}, + packet_parser::parse_commands_from_packet, + server::Server, + }, +}; + +pub struct Hub; +#[async_trait::async_trait] +impl Server for Hub { + async fn handle( + state: Arc>, + stream: TcpStream, + _address: SocketAddr, + count: usize, + ) -> Result<(), Box> { + 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(&create_text(Text { + sender: get_config()?.worldsmaster_username, + content: get_config()?.worldsmaster_greeting, + })).await?; + peer.bytes.get_mut() + .write_all(&create_action()).await?; + trace!("sent text to {}", username); + } + BUDDYLISTUPDATE => { + let buddy = parse_buddy_list_update(msg.to_vec()); + trace!("received buddy list update from {}: {}", username, buddy.buddy); + peer.bytes.get_mut() + .write_all(&create_buddy_list_notify(&buddy)).await?; + trace!("sent buddy list notify to {}: {}", username, buddy.buddy); + } + ROOMIDRQ => { + let room = parse_room_id_request(msg.to_vec()); + trace!("received room id request from {}: {}", username, room); + debug!("{:?}", create_room_id_request(&room, 0x04)); + } + SESSEXIT => { + trace!("received session exit from {}", username); break; + } + TEXT => { + let text = parse_text(msg.to_vec(), &username); + trace!("received text from {}:{}", username, text.content); + + { + state.lock().await.broadcast(&create_text(Text { + sender: username.clone(), + content: text.content, + })).await; + } + trace!("broadcasted text to hub"); + } + _ => (), + } + } + } + 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 new file mode 100644 index 0000000..4f0f38b --- /dev/null +++ b/src/server/interaction/mod.rs @@ -0,0 +1,5 @@ +// Copyleft 2021-2021 Whirlsplash +// 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 new file mode 100644 index 0000000..c0f5223 --- /dev/null +++ b/src/server/interaction/peer.rs @@ -0,0 +1,49 @@ +// Copyleft 2021-2021 Whirlsplash +// 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, + pub rx: Rx, +} +impl Peer { + pub async fn new( + state: Arc>, + bytes: Framed, + username: String, + ) -> std::io::Result { + 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>, + 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 new file mode 100644 index 0000000..fec5980 --- /dev/null +++ b/src/server/interaction/shared.rs @@ -0,0 +1,28 @@ +// Copyleft 2021-2021 Whirlsplash +// 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, +} +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 new file mode 100644 index 0000000..8cd477d --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,12 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +pub mod cmd; +mod interaction; +pub mod net; + +pub mod distributor; +pub mod hub; +mod packet_parser; +pub mod server; +mod types; diff --git a/src/server/net/constants.rs b/src/server/net/constants.rs new file mode 100644 index 0000000..04d94a9 --- /dev/null +++ b/src/server/net/constants.rs @@ -0,0 +1,93 @@ +// Copyleft 2021-2021 Whirlsplash +// 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 new file mode 100644 index 0000000..148a35e --- /dev/null +++ b/src/server/net/converter.rs @@ -0,0 +1,57 @@ +// Copyleft 2021-2021 Whirlsplash +// 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, +) -> Vec { + 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 new file mode 100644 index 0000000..c88ab7f --- /dev/null +++ b/src/server/net/mod.rs @@ -0,0 +1,7 @@ +// Copyleft 2021-2021 Whirlsplash +// 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 new file mode 100644 index 0000000..8a4f960 --- /dev/null +++ b/src/server/net/property_parser.rs @@ -0,0 +1,38 @@ +// Copyleft 2021-2021 Whirlsplash +// 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) -> Vec { + 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 new file mode 100644 index 0000000..0128c0e --- /dev/null +++ b/src/server/net/structure.rs @@ -0,0 +1,18 @@ +// Copyleft 2021-2021 Whirlsplash +// 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 new file mode 100644 index 0000000..d8fd93d --- /dev/null +++ b/src/server/packet_parser.rs @@ -0,0 +1,38 @@ +// Copyleft 2021-2021 Whirlsplash +// 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 { + let mut commands: Vec = 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/server.rs b/src/server/server.rs new file mode 100644 index 0000000..1a6f65b --- /dev/null +++ b/src/server/server.rs @@ -0,0 +1,60 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +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::async_trait] +pub trait Server { + async fn listen(address: &str, server_type: ServerType) -> Result<(), Box> { + 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>, + stream: TcpStream, + _address: SocketAddr, + count: usize, + ) -> Result<(), Box>; +} diff --git a/src/server/types.rs b/src/server/types.rs new file mode 100644 index 0000000..8330875 --- /dev/null +++ b/src/server/types.rs @@ -0,0 +1,8 @@ +// Copyleft 2021-2021 Whirlsplash +// SPDX-License-Identifier: GPL-3.0-only + +use bytes::BytesMut; +use tokio::sync::mpsc; + +pub type Tx = mpsc::UnboundedSender; +pub type Rx = mpsc::UnboundedReceiver; -- cgit v1.2.3