diff options
| author | Gustav Sörnäs <gustav@sornas.net> | 2020-10-21 19:40:28 +0200 |
|---|---|---|
| committer | Gustav Sörnäs <gustav@sornas.net> | 2020-10-21 19:40:28 +0200 |
| commit | 161f58f3e6a0088fa2612d9af54c7b2939be37e7 (patch) | |
| tree | 78d3532e46525db78a48b5f8bcd27ebdac693f6e /mumd/src/state.rs | |
| parent | 92d64a493ced079645e7f0601ff9a573c1616203 (diff) | |
| parent | 962af6bd39f77381aeca874a40fa0b2fb36f33c4 (diff) | |
| download | mum-161f58f3e6a0088fa2612d9af54c7b2939be37e7.tar.gz | |
Merge remote-tracking branch 'origin/refactor-state' into main
Diffstat (limited to 'mumd/src/state.rs')
| -rw-r--r-- | mumd/src/state.rs | 435 |
1 files changed, 14 insertions, 421 deletions
diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 1a02068..f9ed077 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -1,5 +1,10 @@ +pub mod server; +pub mod channel; +pub mod user; + use crate::audio::Audio; use crate::network::ConnectionInfo; +use crate::state::server::Server; use log::*; use mumble_protocol::control::msgs; @@ -8,10 +13,6 @@ use mumble_protocol::voice::Serverbound; use mumlib::command::{Command, CommandResponse}; use mumlib::config::Config; use mumlib::error::{ChannelIdentifierError, Error}; -use mumlib::state::UserDiff; -use serde::{Deserialize, Serialize}; -use std::collections::hash_map::Entry; -use std::collections::HashMap; use std::net::ToSocketAddrs; use tokio::sync::{mpsc, watch}; use crate::network::tcp::{TcpEvent, TcpEventData}; @@ -88,7 +89,7 @@ impl State { }; let mut msg = msgs::UserState::new(); - msg.set_session(self.server.as_ref().unwrap().session_id.unwrap()); + msg.set_session(self.server.as_ref().unwrap().session_id().unwrap()); msg.set_channel_id(id); self.packet_sender.send(msg.into()).unwrap(); (None, Box::new(|_| Ok(None))) @@ -97,7 +98,7 @@ impl State { if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) { return (None, Box::new(|_| Err(Error::DisconnectedError))); } - let list = into_channel( + let list = channel::into_channel( self.server.as_ref().unwrap().channels(), self.server.as_ref().unwrap().users(), ); @@ -118,8 +119,8 @@ impl State { return (None, Box::new(|_| Err(Error::AlreadyConnectedError))); } let mut server = Server::new(); - server.username = Some(username); - server.host = Some(format!("{}:{}", host, port)); + *server.username_mut() = Some(username); + *server.host_mut() = Some(format!("{}:{}", host, port)); self.server = Some(server); self.phase_watcher .0 @@ -194,7 +195,7 @@ impl State { } } - pub fn parse_user_state(&mut self, msg: msgs::UserState) -> Option<UserDiff> { + pub fn parse_user_state(&mut self, msg: msgs::UserState) -> Option<mumlib::state::UserDiff> { if !msg.has_session() { warn!("Can't parse user state without session"); return None; @@ -204,19 +205,18 @@ impl State { if !self.server().unwrap().users().contains_key(&sess) { if !msg.has_name() { warn!("Missing name in initial user state"); - } - if msg.get_name() == self.server().unwrap().username.as_ref().unwrap() { + } else if msg.get_name() == self.server().unwrap().username().unwrap() { // this is us - self.server_mut().unwrap().session_id = Some(sess); + *self.server_mut().unwrap().session_id_mut() = Some(sess); } else { // this is someone else self.audio_mut().add_client(sess); } - self.server_mut().unwrap().users_mut().insert(sess, User::new(msg)); + self.server_mut().unwrap().users_mut().insert(sess, user::User::new(msg)); None } else { let user = self.server_mut().unwrap().users_mut().get_mut(&sess).unwrap(); - let diff = UserDiff::from(msg); + let diff = mumlib::state::UserDiff::from(msg); user.apply_user_diff(&diff); Some(diff) } @@ -275,410 +275,3 @@ impl State { self.server.as_ref().map(|e| e.username()).flatten() } } - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Server { - channels: HashMap<u32, Channel>, - users: HashMap<u32, User>, - pub welcome_text: Option<String>, - - username: Option<String>, - session_id: Option<u32>, - - host: Option<String>, -} - - -impl Server { - pub fn new() -> Self { - Self { - channels: HashMap::new(), - users: HashMap::new(), - welcome_text: None, - username: None, - session_id: None, - host: None, - } - } - - pub fn parse_server_sync(&mut self, mut msg: msgs::ServerSync) { - if msg.has_welcome_text() { - self.welcome_text = Some(msg.take_welcome_text()); - } - } - - pub fn parse_channel_state(&mut self, msg: msgs::ChannelState) { - if !msg.has_channel_id() { - warn!("Can't parse channel state without channel id"); - return; - } - match self.channels.entry(msg.get_channel_id()) { - Entry::Vacant(e) => { - e.insert(Channel::new(msg)); - } - Entry::Occupied(mut e) => e.get_mut().parse_channel_state(msg), - } - } - - pub fn parse_channel_remove(&mut self, msg: msgs::ChannelRemove) { - if !msg.has_channel_id() { - warn!("Can't parse channel remove without channel id"); - return; - } - match self.channels.entry(msg.get_channel_id()) { - Entry::Vacant(_) => { - warn!("Attempted to remove channel that doesn't exist"); - } - Entry::Occupied(e) => { - e.remove(); - } - } - } - - pub fn channels(&self) -> &HashMap<u32, Channel> { - &self.channels - } - - pub fn users(&self) -> &HashMap<u32, User> { - &self.users - } - - pub fn users_mut(&mut self) -> &mut HashMap<u32, User> { - &mut self.users - } - - pub fn username(&self) -> Option<&str> { - self.username.as_ref().map(|e| e.as_str()) - } -} - -impl From<&Server> for mumlib::state::Server { - fn from(server: &Server) -> Self { - mumlib::state::Server { - channels: into_channel(server.channels(), server.users()), - welcome_text: server.welcome_text.clone(), - username: server.username.clone().unwrap(), - host: server.host.as_ref().unwrap().clone(), - } - } -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Channel { - description: Option<String>, - links: Vec<u32>, - max_users: u32, - name: String, - parent: Option<u32>, - position: i32, -} - -impl Channel { - pub fn new(mut msg: msgs::ChannelState) -> Self { - Self { - description: if msg.has_description() { - Some(msg.take_description()) - } else { - None - }, - links: Vec::new(), - max_users: msg.get_max_users(), - name: msg.take_name(), - parent: if msg.has_parent() { - Some(msg.get_parent()) - } else { - None - }, - position: msg.get_position(), - } - } - - pub fn parse_channel_state(&mut self, mut msg: msgs::ChannelState) { - if msg.has_description() { - self.description = Some(msg.take_description()); - } - self.links = msg.take_links(); - if msg.has_max_users() { - self.max_users = msg.get_max_users(); - } - if msg.has_name() { - self.name = msg.take_name(); - } - if msg.has_parent() { - self.parent = Some(msg.get_parent()); - } - if msg.has_position() { - self.position = msg.get_position(); - } - } - - pub fn name(&self) -> &str { - &self.name - } - - pub fn path(&self, channels: &HashMap<u32, Channel>) -> String { - match &self.parent { - Some(t) => format!("{}/{}", channels.get(t).unwrap().path(channels), self.name), - None => self.name.clone(), - } - } -} - -#[derive(Debug)] -struct ProtoTree<'a> { - channel: Option<&'a Channel>, - children: HashMap<u32, ProtoTree<'a>>, - users: Vec<&'a User>, -} - -impl<'a> ProtoTree<'a> { - fn walk_and_add( - &mut self, - channel: &'a Channel, - users: &HashMap<u32, Vec<&'a User>>, - walk: &[u32], - ) { - match walk { - [] => unreachable!("Walks should always have at least one element"), - &[node] => { - let pt = self.children.entry(node).or_insert(ProtoTree { - channel: None, - children: HashMap::new(), - users: Vec::new(), - }); - pt.channel = Some(channel); - pt.users = users.get(&node).map(|e| e.clone()).unwrap_or(Vec::new()); - } - longer => { - self.children - .entry(longer[0]) - .or_insert(ProtoTree { - channel: None, - children: HashMap::new(), - users: Vec::new(), - }) - .walk_and_add(channel, users, &walk[1..]); - } - } - } -} - -impl<'a> From<&ProtoTree<'a>> for mumlib::state::Channel { - fn from(tree: &ProtoTree<'a>) -> Self { - let mut channel = mumlib::state::Channel::from(tree.channel.unwrap()); - let mut children = tree - .children - .iter() - .map(|e| { - ( - e.1.channel.unwrap().position, - mumlib::state::Channel::from(e.1), - ) - }) - .collect::<Vec<_>>(); - children.sort_by_key(|e| (e.0, e.1.name.clone())); - channel.children = children.into_iter().map(|e| e.1).collect(); - channel.users = tree.users.iter().map(|e| (*e).into()).collect(); - channel - } -} - -pub fn into_channel( - channels: &HashMap<u32, Channel>, - users: &HashMap<u32, User>, -) -> mumlib::state::Channel { - let mut walks = Vec::new(); - - let mut channel_lookup = HashMap::new(); - - for user in users.values() { - channel_lookup - .entry(user.channel) - .or_insert(Vec::new()) - .push(user); - } - - for (channel_id, channel) in channels { - let mut walk = Vec::new(); - let mut current = *channel_id; - while let Some(next) = channels.get(¤t).unwrap().parent { - walk.push(current); - current = next; - } - walk.reverse(); - - if walk.len() > 0 { - walks.push((walk, channel)); - } - } - - //root node is ignored because of how walk_and_add is implemented on ProtoTree - let mut proto_tree = ProtoTree { - channel: Some(channels.get(&0).unwrap()), - children: HashMap::new(), - users: channel_lookup - .get(&0) - .map(|e| e.clone()) - .unwrap_or(Vec::new()), - }; - - for (walk, channel) in walks { - proto_tree.walk_and_add(channel, &channel_lookup, &walk); - } - - (&proto_tree).into() -} - -impl From<&Channel> for mumlib::state::Channel { - fn from(channel: &Channel) -> Self { - mumlib::state::Channel { - description: channel.description.clone(), - links: Vec::new(), - max_users: channel.max_users, - name: channel.name.clone(), - children: Vec::new(), - users: Vec::new(), - } - } -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct User { - channel: u32, - comment: Option<String>, - hash: Option<String>, - name: String, - priority_speaker: bool, - recording: bool, - - suppress: bool, // by me - self_mute: bool, // by self - self_deaf: bool, // by self - mute: bool, // by admin - deaf: bool, // by admin -} - -impl User { - pub fn new(mut msg: msgs::UserState) -> Self { - Self { - channel: msg.get_channel_id(), - comment: if msg.has_comment() { - Some(msg.take_comment()) - } else { - None - }, - hash: if msg.has_hash() { - Some(msg.take_hash()) - } else { - None - }, - name: msg.take_name(), - priority_speaker: msg.has_priority_speaker() && msg.get_priority_speaker(), - recording: msg.has_recording() && msg.get_recording(), - suppress: msg.has_suppress() && msg.get_suppress(), - self_mute: msg.has_self_mute() && msg.get_self_mute(), - self_deaf: msg.has_self_deaf() && msg.get_self_deaf(), - mute: msg.has_mute() && msg.get_mute(), - deaf: msg.has_deaf() && msg.get_deaf(), - } - } - - pub fn parse_user_state(&mut self, mut msg: msgs::UserState) { - if msg.has_channel_id() { - self.channel = msg.get_channel_id(); - } - if msg.has_comment() { - self.comment = Some(msg.take_comment()); - } - if msg.has_hash() { - self.hash = Some(msg.take_hash()); - } - if msg.has_name() { - self.name = msg.take_name(); - } - if msg.has_priority_speaker() { - self.priority_speaker = msg.get_priority_speaker(); - } - if msg.has_recording() { - self.recording = msg.get_recording(); - } - if msg.has_suppress() { - self.suppress = msg.get_suppress(); - } - if msg.has_self_mute() { - self.self_mute = msg.get_self_mute(); - } - if msg.has_self_deaf() { - self.self_deaf = msg.get_self_deaf(); - } - if msg.has_mute() { - self.mute = msg.get_mute(); - } - if msg.has_deaf() { - self.deaf = msg.get_deaf(); - } - } - - pub fn apply_user_diff(&mut self, diff: &UserDiff) { - debug!("applying user diff\n{:#?}", diff); - if let Some(comment) = diff.comment.clone() { - self.comment = Some(comment); - } - if let Some(hash) = diff.hash.clone() { - self.hash = Some(hash); - } - if let Some(name) = diff.name.clone() { - self.name = name; - } - if let Some(priority_speaker) = diff.priority_speaker { - self.priority_speaker = priority_speaker; - } - if let Some(recording) = diff.recording { - self.recording = recording; - } - if let Some(suppress) = diff.suppress { - self.suppress = suppress; - } - if let Some(self_mute) = diff.self_mute { - self.self_mute = self_mute; - } - if let Some(self_deaf) = diff.self_deaf { - self.self_deaf = self_deaf; - } - if let Some(mute) = diff.mute { - self.mute = mute; - } - if let Some(deaf) = diff.deaf { - self.deaf = deaf; - } - - if let Some(channel_id) = diff.channel_id { - self.channel = channel_id; - } - } - - pub fn name(&self) -> &str { - &self.name - } - - pub fn channel(&self) -> u32 { - self.channel - } -} - -impl From<&User> for mumlib::state::User { - fn from(user: &User) -> Self { - mumlib::state::User { - comment: user.comment.clone(), - hash: user.hash.clone(), - name: user.name.clone(), - priority_speaker: user.priority_speaker, - recording: user.recording, - suppress: user.suppress, - self_mute: user.self_mute, - self_deaf: user.self_deaf, - mute: user.mute, - deaf: user.deaf, - } - } -} |
