aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorFuwn <[email protected]>2021-03-20 15:46:12 +0000
committerFuwn <[email protected]>2021-03-20 15:46:12 +0000
commit2abd749036d29fc7452684fae85ab039186297d9 (patch)
tree24b450fe1c47b7d52234eecef49c50a7e6008e4b /src/server
parentfix: formatting (diff)
downloadwhirl-2abd749036d29fc7452684fae85ab039186297d9.tar.xz
whirl-2abd749036d29fc7452684fae85ab039186297d9.zip
whirl: :star:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/auto.rs8
-rw-r--r--src/server/mod.rs2
-rw-r--r--src/server/world.rs177
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();
+ // },
+ _ => ()
+ }
+ }
+ }
+ }
+}