diff options
Diffstat (limited to 'src/server_dev/room/server.rs')
| -rw-r--r-- | src/server_dev/room/server.rs | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/src/server_dev/room/server.rs b/src/server_dev/room/server.rs new file mode 100644 index 0000000..63a13f6 --- /dev/null +++ b/src/server_dev/room/server.rs @@ -0,0 +1,434 @@ +use std::{ + collections::{HashMap, HashSet}, + error::Error, + io::{ErrorKind, Read, Write}, + str::from_utf8, +}; + +use bytes::BytesMut; +use mio::{ + event::Event, + net::{TcpListener, TcpStream}, + Events, + Interest, + Poll, + Registry, + Token, +}; + +use crate::{ + config::get_config, + server::{ + auto::cmd::{ + property::{create_property_request_command, create_property_update_command}, + room::create_room_id_redirect_command, + }, + cmd::{ + buddy_list::create_buddy_list_notify_command, + property::parse_property_set_command, + text::{create_text_command, create_text_command_with_action}, + }, + parser::get_commands_from_buffer, + room::cmd::session::parse_session_initialization_command, + }, +}; + +const SERVER: Token = Token(0); + +pub struct RoomServer { + pub clients: HashMap<Token, String>, + pub connections: HashMap<Token, TcpStream>, + pub room_ids: Vec<String>, +} +impl RoomServer { + pub fn listen(&mut self, addr: &str) -> Result<(), Box<dyn Error>> { + let mut listener = TcpListener::bind(addr.parse().unwrap())?; + let mut poll = Poll::new()?; + let mut events = Events::with_capacity(1024); + let mut counter: usize = 0; + // let mut sockets = HashMap::new(); + let mut requests = HashMap::new(); + let mut buffer = [0 as u8; 1024]; + // let mut room_ids = vec![]; + + poll + .registry() + .register(&mut listener, Token(0), Interest::READABLE)?; + + debug!( + "RoomServer now listening on {}", + listener.local_addr().unwrap() + ); + + loop { + poll.poll(&mut events, None)?; + + for event in &events { + match event.token() { + Token(0) => { + loop { + match listener.accept() { + Ok((mut stream, address)) => { + counter += 1; + let token = Token(counter); + + poll + .registry() + .register(&mut stream, token, Interest::READABLE)?; + + debug!( + "registered peer with address '{}' as '{}'", + address, token.0 + ); + + // sockets.insert(token, stream); + self.connections.insert(token, stream); + requests.insert(token, Vec::with_capacity(192)); + } + Err(ref err) if err.kind() == ErrorKind::WouldBlock => break, + Err(err) => { + error!("unexpected error: {}", err); + poll + .registry() + .deregister(self.connections.get_mut(&Token(counter)).unwrap())?; + break; + } + } + } + } + token if event.is_readable() => { + loop { + let read = self.connections.get_mut(&token).unwrap().read(&mut buffer); + match read { + Ok(0) => { + self.connections.remove(&token); + break; + } + Ok(n) => { + let req = requests.get_mut(&token).unwrap(); + for b in &buffer[0..n] { + req.push(*b); + } + + for cmd in get_commands_from_buffer(BytesMut::from(&buffer[..n])) { + match cmd.get(2).unwrap() { + 10 => { + // PROPREQ + debug!("received property request command from client 'null'"); + self + .connections + .get_mut(&token) + .unwrap() + .write_all(&create_property_update_command()) + .unwrap(); + debug!("sent property update command to client 'null'"); + } + 6 => { + // SESSINIT + let local_username = parse_session_initialization_command(cmd).username; + self.clients.insert(token, local_username.clone()); + debug!( + "received session initialization command from client '{}'", + local_username, + ); + self + .connections + .get_mut(&token) + .unwrap() + .write_all(&create_property_request_command()) + .unwrap(); + debug!( + "sent session initialization command to client '{}'", + local_username + ); + } + 15 => { + // PROPSET + let avatar = parse_property_set_command(cmd); + debug!( + "received property set command from client '{}': {}", + self.clients.get(&token).unwrap(), + avatar, + ); + self + .connections + .get_mut(&token) + .unwrap() + .write_all(&create_text_command_with_action( + "WORLDSMASTER", + &get_config().unwrap().worldsmaster_greeting, + )) + .unwrap(); + debug!( + "sent session initialization command to client '{}'", + self.clients.get(&token).unwrap(), + ); + } + 29 => { + // BUDDYLISTUPDATE + let received_buddy = from_utf8( + cmd + .get(4..cmd.get(0).unwrap().to_owned() as usize - 1) + .unwrap(), + ) + .unwrap(); + debug!( + "received buddy list update command from client '{}': {}", + self.clients.get(&token).unwrap(), + received_buddy, + ); + self + .connections + .get_mut(&token) + .unwrap() + .write_all(&create_buddy_list_notify_command(received_buddy)) + .unwrap(); + debug!( + "sent buddy list notify command to client '{}'", + self.clients.get(&token).unwrap(), + ); + } + // 20 => { // ROOMIDRQ + // let room_name = from_utf8( + // cmd.get(4..cmd.get(0).unwrap().to_owned() as usize).unwrap() + // ).unwrap(); + // debug!( + // "received room id request command from client '{}': {}", + // self.clients.get(&token).unwrap(), + // room_name, + // ); + // let room_id; + // if !self.room_ids.contains(&room_name.to_string()) { + // self.room_ids.push(room_name.to_string()); + // room_id = self.room_ids.iter() + // .position(|i| i == &room_name.to_string()) + // .unwrap(); + // trace!("inserted room '{}' as '{}'", room_name, room_id); + // } else { + // let position = self.room_ids.iter() + // .position(|i| i == &room_name.to_string()) + // .unwrap(); + // trace!("found room '{}' as '{}'", room_name, position); + // room_id = position; + // } + // trace!("room name: {}, room id: {}", room_name, room_id); + // trace!("{:?}", self.room_ids); + // self.connections.get_mut(&token).unwrap() + // .write_all(&create_room_id_redirect_command( + // room_name, room_id, + // )).unwrap(); + // } + 14 => { + // TEXT + let text = + from_utf8(cmd.get(6..cmd.get(0).unwrap().to_owned() as usize).unwrap()) + .unwrap(); + let username = self.clients.get(&token).unwrap().clone(); + debug!( + "received text command from client '{}': {}", + username, + format!("room: {}", text), + ); + self.connections.iter_mut().for_each(|t| { + t.1 + .write_all(&create_text_command(&username, text)) + .unwrap() + }); + debug!("broadcasted text command to clients"); + } + 7 => { + // SESSEXIT + debug!( + "received session exit command from client '{}'", + self.clients.get(&token).unwrap(), + ); + } + _ => (), + } + } + } + Err(ref err) if err.kind() == ErrorKind::WouldBlock => break, + Err(err) => { + error!("unexpected error: {}", err); + break; + } + } + } + } + _ => (), + } + } + } + } + + fn broadcast(sockets: &HashMap<Token, TcpStream>, cmd: &[u8]) -> () { + for mut socket in sockets { + socket.1.write_all(cmd).unwrap(); + } + } + + // fn process( + // &mut self, + // _registry: &Registry, + // event: &Event, + // token: Token, + // ) -> Result<bool, Box<dyn Error>> { + // if event.is_readable() { + // let mut connection_closed = false; + // let mut received_data = vec![0; 4096]; + // let mut bytes_read = 0; + // + // let stream = self.connections.get_mut(&token).unwrap(); + // + // loop { + // match stream.read(&mut received_data[bytes_read..]) { + // Ok(0) => { + // connection_closed = true; + // break; + // } + // Ok(n) => { + // bytes_read += n; + // if bytes_read == received_data.len() { + // received_data.resize(received_data.len() + 1024, 0); + // } + // } + // Err(ref err) if err.kind() == ErrorKind::WouldBlock => break, + // Err(ref err) if err.kind() == ErrorKind::Interrupted => continue, + // Err(err) => return Err(Box::new(err)), + // } + // } + // + // if bytes_read != 0 { + // self.handle( + // &mut received_data[..bytes_read], + // token, + // ); + // } + // if connection_closed { + // println!("de-registered peer with token '{}'", token.0); + // return Ok(true); + // } + // } + // + // Ok(false) + // } + + // fn handle( + // &mut self, + // data: &[u8], + // // stream: &mut TcpStream, + // token: Token, + // ) -> () { + // // trace!("i am client: {:?}", self.clients.get(&token)); + // // debug!("{:?}", self.connections); + // for cmd in get_commands_from_buffer(BytesMut::from(data)) { + // debug!("received: {:?}", cmd); + // match cmd.get(2).unwrap() { + // 10 => { // PROPREQ + // debug!("received property request command from client 'null'"); + // self.connections.get_mut(&token).unwrap() + // .write_all(&create_property_update_command()).unwrap(); + // debug!("sent property update command to client 'null'"); + // } + // 6 => { // SESSINIT + // let local_username = + // parse_session_initialization_command(cmd).username; + // self.clients.insert(token, local_username.clone()); + // debug!( + // "received session initialization command from client '{}'", + // local_username, + // ); + // self.connections.get_mut(&token).unwrap() + // .write_all(&create_property_request_command()).unwrap(); + // debug!("sent session initialization command to client '{}'", local_username); + // } + // 15 => { // PROPSET + // let avatar = parse_property_set_command(cmd); + // debug!( + // "received property set command from client '{}': {}", + // self.clients.get(&token).unwrap(), + // avatar, + // ); + // self.connections.get_mut(&token).unwrap() + // .write_all(&create_text_command_with_action( + // "WORLDSMASTER", &get_config().unwrap().worldsmaster_greeting, + // )).unwrap(); + // debug!( + // "sent session initialization command to client '{}'", + // self.clients.get(&token).unwrap(), + // ); + // } + // 29 => { // BUDDYLISTUPDATE + // let received_buddy = from_utf8( + // cmd.get(4..cmd.get(0).unwrap().to_owned() as usize - 1).unwrap() + // ).unwrap(); + // debug!( + // "received buddy list update command from client '{}': {}", + // self.clients.get(&token).unwrap(), + // received_buddy, + // ); + // self.connections.get_mut(&token).unwrap() + // .write_all(&create_buddy_list_notify_command(received_buddy)).unwrap(); + // debug!( + // "sent buddy list notify command to client '{}'", + // self.clients.get(&token).unwrap(), + // ); + // } + // 20 => { // ROOMIDRQ + // let room_name = from_utf8( + // cmd.get(4..cmd.get(0).unwrap().to_owned() as usize).unwrap() + // ).unwrap(); + // debug!( + // "received room id request command from client '{}': {}", + // self.clients.get(&token).unwrap(), + // room_name, + // ); + // let room_id; + // if !self.room_ids.contains(&room_name.to_string()) { + // self.room_ids.push(room_name.to_string()); + // room_id = self.room_ids.iter() + // .position(|i| i == &room_name.to_string()) + // .unwrap(); + // trace!("inserted room '{}' as '{}'", room_name, room_id); + // } else { + // let position = self.room_ids.iter() + // .position(|i| i == &room_name.to_string()) + // .unwrap(); + // trace!("found room '{}' as '{}'", room_name, position); + // room_id = position; + // } + // trace!("room name: {}, room id: {}", room_name, room_id); + // trace!("{:?}", self.room_ids); + // self.connections.get_mut(&token).unwrap() + // .write_all(&create_room_id_redirect_command( + // room_name, room_id, + // )).unwrap(); + // } + // 14 => { // TEXT + // let text = from_utf8( + // cmd.get(6..cmd.get(0).unwrap().to_owned() as usize).unwrap() + // ).unwrap(); + // let username = self.clients.get(&token).unwrap().clone(); + // debug!( + // "received text command from client '{}': {}", + // username, text, + // ); + // self.connections.iter_mut().for_each(|t| + // t.1.write_all(&create_text_command( + // &username, + // text, + // )).unwrap() + // ); + // debug!("broadcasted text command to clients"); + // } + // 7 => { // SESSEXIT + // debug!( + // "received session exit command from client '{}'", + // self.clients.get(&token).unwrap(), + // ); + // } + // _ => (), + // } + // } + // } +} |