diff options
| author | Fuwn <[email protected]> | 2021-03-20 15:46:12 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2021-03-20 15:46:12 +0000 |
| commit | 2abd749036d29fc7452684fae85ab039186297d9 (patch) | |
| tree | 24b450fe1c47b7d52234eecef49c50a7e6008e4b /src/server | |
| parent | fix: formatting (diff) | |
| download | whirl-2abd749036d29fc7452684fae85ab039186297d9.tar.xz whirl-2abd749036d29fc7452684fae85ab039186297d9.zip | |
whirl: :star:
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/auto.rs | 8 | ||||
| -rw-r--r-- | src/server/mod.rs | 2 | ||||
| -rw-r--r-- | src/server/world.rs | 177 |
3 files changed, 187 insertions, 0 deletions
diff --git a/src/server/auto.rs b/src/server/auto.rs new file mode 100644 index 0000000..7a834b0 --- /dev/null +++ b/src/server/auto.rs @@ -0,0 +1,8 @@ +use mio::net::TcpListener; + +pub struct AutoServer; +impl AutoServer { + pub fn new(_listener: TcpListener) { + unimplemented!(); + } +}
\ No newline at end of file diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..4d08f2b --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,2 @@ +pub mod auto; +pub mod world; diff --git a/src/server/world.rs b/src/server/world.rs new file mode 100644 index 0000000..19e7ce7 --- /dev/null +++ b/src/server/world.rs @@ -0,0 +1,177 @@ +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::sub::buddy_list::create_buddy_list_notify_command; +use crate::sub::text::create_text_command; +use crate::sub::property::{create_property_update_command, create_property_request_command}; + +pub struct WorldServer; +impl WorldServer { + 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); break } + } + } + }, + token if event.readiness().is_readable() => { + // println!("readable"); + loop { + let read = sockets.get_mut(&token).unwrap().read(&mut buffer); + match read { + Ok(0) => { + // println!("read 0 bytes: {:?}", buffer); + sockets.remove(&token); + break + }, + Ok(n) => { + // println!("read {:?} bytes: {:?}", &n, buffer); + 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); + + for mut socket in &sockets { + socket.1.write_all(&create_text_command(message)).unwrap(); + } + } + // 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(); + // }, + _ => () + } + } + } + } +} |