diff options
| author | Fuwn <[email protected]> | 2021-03-22 21:50:26 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2021-03-22 21:50:26 +0000 |
| commit | d4e5c30fd9d2eecdd2af55fd4ee5c0da4cda3f55 (patch) | |
| tree | 32b33ace94dbb89cc67aa3cad6e06e9376902b88 /src/server/room | |
| parent | feature: Use feature "hash_set_entry" (diff) | |
| download | whirl-d4e5c30fd9d2eecdd2af55fd4ee5c0da4cda3f55.tar.xz whirl-d4e5c30fd9d2eecdd2af55fd4ee5c0da4cda3f55.zip | |
etc: Correct struct names
Diffstat (limited to 'src/server/room')
| -rw-r--r-- | src/server/room/cmd/mod.rs | 1 | ||||
| -rw-r--r-- | src/server/room/cmd/property.rs | 47 | ||||
| -rw-r--r-- | src/server/room/mod.rs | 3 | ||||
| -rw-r--r-- | src/server/room/server.rs | 181 | ||||
| -rw-r--r-- | src/server/room/utils.rs | 0 |
5 files changed, 232 insertions, 0 deletions
diff --git a/src/server/room/cmd/mod.rs b/src/server/room/cmd/mod.rs new file mode 100644 index 0000000..f348cd0 --- /dev/null +++ b/src/server/room/cmd/mod.rs @@ -0,0 +1 @@ +pub mod property; diff --git a/src/server/room/cmd/property.rs b/src/server/room/cmd/property.rs new file mode 100644 index 0000000..b75efad --- /dev/null +++ b/src/server/room/cmd/property.rs @@ -0,0 +1,47 @@ +pub fn create_property_update_command() -> [u8; 161] { // Vec<u8> + // let mut property = Vec::with_capacity(2); + // property.push(0x01); // ? + // property.push(0x10); // Command type + // + // // Meaningful Data + // property.push(); // Property ID + // property.push(); // Flags + // property.push(); // Access + // + // // Insert data length as first byte. + // property.insert(0, property.len() as u8 + 1); // ^ + // + // property // Return created array + + [ + 0xA1, 0xFF, 0x10, 0x08, 0x80, 0x01, 0x07, 0x31, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1B, 0x80, + 0x01, 0x0C, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x73, + 0x33, 0x64, 0x2E, 0x63, 0x6F, 0x6D, 0x1A, 0x80, + 0x01, 0x15, 0x6D, 0x61, 0x69, 0x6C, 0x2E, 0x75, + 0x73, 0x2E, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x73, + 0x2E, 0x6E, 0x65, 0x74, 0x3A, 0x32, 0x35, 0x19, + 0x80, 0x01, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3A, + 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2D, 0x64, 0x79, + 0x6E, 0x61, 0x6D, 0x69, 0x63, 0x2E, 0x75, 0x73, + 0x2E, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x73, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x63, 0x67, 0x69, 0x2D, + 0x62, 0x69, 0x6E, 0x18, 0x80, 0x01, 0x1F, 0x68, + 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, + 0x77, 0x2D, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, + 0x2E, 0x75, 0x73, 0x2E, 0x77, 0x6F, 0x72, 0x6C, + 0x64, 0x73, 0x2E, 0x6E, 0x65, 0x74, 0x0F, 0x80, + 0x01, 0x01, 0x33, 0x03, 0x80, 0x01, 0x02, 0x32, + 0x34, 0x01, 0x80, 0x01, 0x0C, 0x57, 0x4F, 0x52, + 0x4C, 0x44, 0x53, 0x4D, 0x41, 0x53, 0x54, 0x45, + 0x52 + ]: [u8; 161] +} + +pub fn create_property_request_command() -> [u8; 22] { + [ + 0x16, 0x01, 0x06, 0x04, 0x01, 0x30, 0x0f, 0x01, + 0x33, 0x08, 0x07, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x03, 0x02, 0x32, 0x34 + ]: [u8; 22] +} diff --git a/src/server/room/mod.rs b/src/server/room/mod.rs new file mode 100644 index 0000000..7ceb58d --- /dev/null +++ b/src/server/room/mod.rs @@ -0,0 +1,3 @@ +pub mod cmd; +pub mod server; +pub mod utils; diff --git a/src/server/room/server.rs b/src/server/room/server.rs new file mode 100644 index 0000000..27a8b24 --- /dev/null +++ b/src/server/room/server.rs @@ -0,0 +1,181 @@ +use mio::net::{TcpListener, TcpStream}; +use std::io::{Read, Write}; +use mio::{Poll, Token, Ready, PollOpt, Events}; +use std::collections::HashMap; +use std::str::from_utf8; +use crate::cmd::buddy_list::create_buddy_list_notify_command; +use crate::cmd::text::create_text_command; +// use crate::cmd::property::{create_property_update_command, create_property_request_command}; +use crate::server::room::cmd::property::{create_property_update_command, create_property_request_command}; +use rand::Rng; +use crate::server::utils::broadcast_to_all_clients; + +pub struct RoomServer; +impl RoomServer { + pub fn new(listener: TcpListener) { + let poll = Poll::new().unwrap(); + poll.register( + &listener, + Token(0), + Ready::readable(), + PollOpt::edge() + ).unwrap(); + + let mut counter: usize = 0; + let mut sockets: HashMap<Token, TcpStream> = HashMap::new(); + let mut requests: HashMap<Token, Vec<u8>> = HashMap::new(); + let mut buffer = [0 as u8; 1024]; + + let mut events = Events::with_capacity(1024); + loop { + poll.poll(&mut events, None).unwrap(); + for event in &events { + match event.token() { + Token(0) => { + loop { + match listener.accept() { + Ok((socket, address)) => { + counter += 1; + let token = Token(counter); + + poll.register( + &socket, + token, + Ready::readable(), + PollOpt::edge() + ).unwrap(); + + info!( + "registered ip '{}' with token '{}'", + address.ip(), token.0 + ); + + sockets.insert(token, socket); + requests.insert(token, Vec::with_capacity(192)); + } + Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => + break, + Err(e) => { + error!("unexpected error: {}", e); + poll.deregister(sockets.get(&Token(counter)).unwrap()).unwrap(); + break; + } + } + } + }, + token if event.readiness().is_readable() => { + loop { + let read = sockets.get_mut(&token).unwrap().read(&mut buffer); + match read { + Ok(0) => { sockets.remove(&token); break; } + Ok(n) => { + let req = requests.get_mut(&token).unwrap(); + for b in &buffer[0..n] { + req.push(*b); + } + + // First byte means how long data section of the packet is. + // Second byte is to be determined. + // Third byte is the request type. + + // Match packet type by descriptor; **third** byte. + match &buffer.get(2).unwrap() { // Third byte is 2 because Rust is zero-indexed. + // PROPREQ + 10 => { + info!("received property request command"); + sockets.get_mut(&token).unwrap() + .write_all(&create_property_update_command()).unwrap(); + info!("sent property update"); + } + // SESSINIT + 6 => { + info!("received session initialization command"); + sockets.get_mut(&token).unwrap() + .write_all(&create_property_request_command()).unwrap(); + info!("sent session initialization command") + } + // PROPSET + 15 => info!("received property set command"), + // BUDDYLISTUPDATE + 29 => { + info!("received buddy list update command"); + sockets.get_mut(&token).unwrap() + .write_all(&create_buddy_list_notify_command("Wirlaburla")) + .unwrap(); + info!("sent buddy notify update command") + } + // ROOMIDRQ + 20 => info!("received room id request command"), + // TEXT + 14 => { + info!("received text command"); + + // TODO: Make this into a command! + let message = from_utf8( + &buffer[6..*&buffer.get(0).unwrap().to_owned() as usize] + ).unwrap(); + info!("message: {}", message); + + // Using User as a placeholder. Ideally, this would print out the username of + // the one who sent it. + broadcast_to_all_clients( + &sockets, + &create_text_command( + // Random integer is added to the end of "User", just a development + // proof-of-concept. Since at this stage usernames aren't exactly kept, + // we can identify message senders as their connection token; `token.0`. + &format!("User{}", rand::thread_rng().gen_range(1..150).to_string()), + message + ) + ); + } + // SESSEXIT + 7 => { + info!("received session termination command"); + poll.deregister(sockets.get(&token).unwrap()).unwrap(); + info!("de-registered client: {}", token.0); + } + // Anything else, do nothing. + _ => () + } + } + Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => + break, + Err(e) => { error!("unexpected error: {}", e); break; } + } + } + + // Unimplemented + // let ready = requests.get(&token).unwrap() + // .windows(4) + // .find(|window| is_double_crnl(*window)) + // .is_some(); + // + // if ready { + // let socket = sockets.get(&token).unwrap(); + // poll.reregister( + // socket, + // token, + // Ready::writable(), + // PollOpt::edge() | PollOpt::oneshot()).unwrap(); + // } + }, + // Unimplemented + // token if event.readiness().is_writable() => { + // println!("writeable"); + // requests.get_mut(&token).unwrap().clear(); + // sockets.get_mut(&token).unwrap().write_all("test".as_bytes()).unwrap(); + // + // // Re-use existing connection ("keep-alive") - switch back to reading + // poll.reregister( + // sockets.get(&token).unwrap(), + // token, + // Ready::readable(), + // PollOpt::edge()).unwrap(); + // }, + _ => () + } + } + } + } +} diff --git a/src/server/room/utils.rs b/src/server/room/utils.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/server/room/utils.rs |