diff options
Diffstat (limited to 'mumd')
| -rw-r--r-- | mumd/Cargo.toml | 1 | ||||
| -rw-r--r-- | mumd/src/main.rs | 2 | ||||
| -rw-r--r-- | mumd/src/network/tcp.rs | 13 | ||||
| -rw-r--r-- | mumd/src/notify.rs | 19 | ||||
| -rw-r--r-- | mumd/src/state.rs | 113 | ||||
| -rw-r--r-- | mumd/src/state/user.rs | 12 |
6 files changed, 129 insertions, 31 deletions
diff --git a/mumd/Cargo.toml b/mumd/Cargo.toml index e27c2a8..350d81e 100644 --- a/mumd/Cargo.toml +++ b/mumd/Cargo.toml @@ -17,6 +17,7 @@ cpal = { git = "https://github.com/RustAudio/cpal" } futures = "0.3" futures-util = "0.3" ipc-channel = "0.14" +libnotify = "1.0" log = "0.4" mumble-protocol = "0.3" native-tls = "0.2" diff --git a/mumd/src/main.rs b/mumd/src/main.rs index e88eede..37ff0dd 100644 --- a/mumd/src/main.rs +++ b/mumd/src/main.rs @@ -1,6 +1,7 @@ mod audio; mod command; mod network; +mod notify; mod state; use crate::network::ConnectionInfo; @@ -22,6 +23,7 @@ use tokio::task::spawn_blocking; #[tokio::main] async fn main() { setup_logger(std::io::stderr(), true); + notify::init(); // Oneshot channel for setting UDP CryptState from control task // For simplicity we don't deal with re-syncing, real applications would have to. diff --git a/mumd/src/network/tcp.rs b/mumd/src/network/tcp.rs index c2cb234..630f46a 100644 --- a/mumd/src/network/tcp.rs +++ b/mumd/src/network/tcp.rs @@ -250,24 +250,15 @@ async fn listen( } ControlPacket::UserState(msg) => { let mut state = state.lock().unwrap(); - let session = msg.get_session(); if *state.phase_receiver().borrow() == StatePhase::Connecting { state.audio_mut().add_client(msg.get_session()); state.parse_user_state(*msg); } else { state.parse_user_state(*msg); } - let server = state.server_mut().unwrap(); - let user = server.users().get(&session).unwrap(); - info!("User {} connected to {}", user.name(), user.channel()); } ControlPacket::UserRemove(msg) => { - info!("User {} left", msg.get_session()); - state - .lock() - .unwrap() - .audio_mut() - .remove_client(msg.get_session()); + state.lock().unwrap().remove_client(*msg); } ControlPacket::ChannelState(msg) => { debug!("Channel state received"); @@ -367,4 +358,4 @@ async fn run_until_disconnection<T, F, G, H>( }; join!(main_block, phase_transition_block); -}
\ No newline at end of file +} diff --git a/mumd/src/notify.rs b/mumd/src/notify.rs new file mode 100644 index 0000000..5bb1a26 --- /dev/null +++ b/mumd/src/notify.rs @@ -0,0 +1,19 @@ +use log::*; + +pub fn init() { + libnotify::init("mumd").unwrap(); +} + +pub fn send(msg: String) -> bool { + match libnotify::Notification::new( + "mumd", + Some(msg.as_str()), + None, + ).show() { + Ok(_) => { true } + Err(_) => { + debug!("Unable to send notification"); + false + } + } +} diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 44d8b21..ea081fc 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -4,6 +4,7 @@ pub mod user; use crate::audio::Audio; use crate::network::ConnectionInfo; +use crate::notify; use crate::state::server::Server; use log::*; @@ -13,6 +14,7 @@ use mumble_protocol::voice::Serverbound; use mumlib::command::{Command, CommandResponse}; use mumlib::config::Config; use mumlib::error::{ChannelIdentifierError, Error}; +use mumlib::state::UserDiff; use std::net::ToSocketAddrs; use tokio::sync::{mpsc, watch}; use crate::network::tcp::{TcpEvent, TcpEventData}; @@ -205,31 +207,106 @@ impl State { } } - pub fn parse_user_state(&mut self, msg: msgs::UserState) -> Option<mumlib::state::UserDiff> { + pub fn parse_user_state(&mut self, msg: msgs::UserState) -> Option<UserDiff> { if !msg.has_session() { warn!("Can't parse user state without session"); return None; } - let sess = msg.get_session(); + let session = msg.get_session(); // check if this is initial state - if !self.server().unwrap().users().contains_key(&sess) { - if !msg.has_name() { - warn!("Missing name in initial user state"); - } else if msg.get_name() == self.server().unwrap().username().unwrap() { - // this is us - *self.server_mut().unwrap().session_id_mut() = Some(sess); - } else { - // this is someone else - self.audio_mut().add_client(sess); + if !self.server().unwrap().users().contains_key(&session) { + self.parse_initial_user_state(session, msg); + return None; + } else { + return Some(self.parse_updated_user_state(session, msg)); + } + } + + fn parse_initial_user_state(&mut self, session: u32, msg: msgs::UserState) { + if !msg.has_name() { + warn!("Missing name in initial user state"); + } else if msg.get_name() == self.server().unwrap().username().unwrap() { + // this is us + *self.server_mut().unwrap().session_id_mut() = Some(session); + } else { + // this is someone else + self.audio_mut().add_client(session); + + // send notification only if we've passed the connecting phase + if *self.phase_receiver().borrow() == StatePhase::Connected { + let channel_id = if msg.has_channel_id() { + msg.get_channel_id() + } else { + 0 + }; + if let Some(channel) = self.server().unwrap().channels().get(&channel_id) { + notify::send(format!("{} connected and joined {}", &msg.get_name(), channel.name())); + } } - self.server_mut().unwrap().users_mut().insert(sess, user::User::new(msg)); + } + self.server_mut().unwrap().users_mut().insert(session, user::User::new(msg)); + } + + fn parse_updated_user_state(&mut self, session: u32, msg: msgs::UserState) -> UserDiff { + let user = self.server_mut().unwrap().users_mut().get_mut(&session).unwrap(); + + let mute = if msg.has_self_mute() && user.self_mute() != msg.get_self_mute() { + Some(msg.get_self_mute()) + } else { None + }; + let deaf = if msg.has_self_deaf() && user.self_deaf() != msg.get_self_deaf() { + Some(msg.get_self_deaf()) } else { - let user = self.server_mut().unwrap().users_mut().get_mut(&sess).unwrap(); - let diff = mumlib::state::UserDiff::from(msg); - user.apply_user_diff(&diff); - Some(diff) + None + }; + + let diff = UserDiff::from(msg); + user.apply_user_diff(&diff); + let user = self.server().unwrap().users().get(&session).unwrap(); + + // send notification if the user moved to or from any channel + //TODO our channel only + if let Some(channel_id) = diff.channel_id { + if let Some(channel) = self.server().unwrap().channels().get(&channel_id) { + notify::send(format!( + "{} moved to channel {}", + &user.name(), + channel.name())); + } else { + warn!("{} moved to invalid channel {}", &user.name(), channel_id); + } } + + // send notification if a user muted/unmuted + //TODO our channel only + let notif_desc = + if let Some(deaf) = deaf { + if deaf { + Some(format!("{} muted and deafend themselves", &user.name())) + } else if !deaf { + Some(format!("{} unmuted and undeafend themselves", &user.name())) + } else { + warn!("Invalid user state received"); + None + } + } else if let Some(mute) = mute { + if mute { + Some(format!("{} muted themselves", &user.name())) + } else if !mute { + Some(format!("{} unmuted themselves", &user.name())) + } else { + warn!("Invalid user state received"); + None + } + } else { + None + }; + if let Some(notif_desc) = notif_desc { + notify::send(notif_desc); + } + + diff } pub fn remove_client(&mut self, msg: msgs::UserRemove) { @@ -237,6 +314,10 @@ impl State { warn!("Tried to remove user state without session"); return; } + if let Some(user) = self.server().unwrap().users().get(&msg.get_session()) { + notify::send(format!("{} disconnected", &user.name())); + } + self.audio().remove_client(msg.get_session()); self.server_mut().unwrap().users_mut().remove(&msg.get_session()); info!("User {} disconnected", msg.get_session()); diff --git a/mumd/src/state/user.rs b/mumd/src/state/user.rs index 679d0ff..848208c 100644 --- a/mumd/src/state/user.rs +++ b/mumd/src/state/user.rs @@ -1,4 +1,3 @@ -use log::*; use mumble_protocol::control::msgs; use serde::{Deserialize, Serialize}; @@ -80,7 +79,6 @@ impl User { } pub fn apply_user_diff(&mut self, diff: &mumlib::state::UserDiff) { - debug!("applying user diff\n{:#?}", diff); if let Some(comment) = diff.comment.clone() { self.comment = Some(comment); } @@ -111,13 +109,11 @@ impl User { 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 } @@ -125,6 +121,14 @@ impl User { pub fn channel(&self) -> u32 { self.channel } + + pub fn self_mute(&self) -> bool { + self.self_mute + } + + pub fn self_deaf(&self) -> bool { + self.self_deaf + } } impl From<&User> for mumlib::state::User { |
