diff options
Diffstat (limited to 'mumd/src/state.rs')
| -rw-r--r-- | mumd/src/state.rs | 205 |
1 files changed, 130 insertions, 75 deletions
diff --git a/mumd/src/state.rs b/mumd/src/state.rs index d93181a..d2d77b1 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -8,14 +8,15 @@ use crate::network::tcp::{TcpEvent, TcpEventData}; use crate::network::{ConnectionInfo, VoiceStreamType}; use crate::notifications; use crate::state::server::Server; - use crate::state::user::UserDiff; + +use chrono::NaiveDateTime; use log::*; use mumble_protocol::control::msgs; use mumble_protocol::control::ControlPacket; use mumble_protocol::ping::PongPacket; use mumble_protocol::voice::Serverbound; -use mumlib::command::{Command, CommandResponse, MessageTarget}; +use mumlib::command::{ChannelTarget, Command, CommandResponse, MessageTarget, MumbleEvent, MumbleEventKind}; use mumlib::config::Config; use mumlib::Error; use std::{ @@ -74,9 +75,11 @@ pub struct State { server: Option<Server>, audio_input: AudioInput, audio_output: AudioOutput, - message_buffer: Vec<(String, u32)>, + message_buffer: Vec<(NaiveDateTime, String, u32)>, phase_watcher: (watch::Sender<StatePhase>, watch::Receiver<StatePhase>), + + events: Vec<MumbleEvent>, } impl State { @@ -97,6 +100,7 @@ impl State { audio_output, message_buffer: Vec::new(), phase_watcher, + events: Vec::new(), }; state.reload_config(); Ok(state) @@ -131,21 +135,25 @@ impl State { // this is someone else // send notification only if we've passed the connecting phase if matches!(*self.phase_receiver().borrow(), StatePhase::Connected(_)) { - let channel_id = msg.get_channel_id(); - - if channel_id - == self.get_users_channel(self.server().unwrap().session_id().unwrap()) - { - if let Some(channel) = self.server().unwrap().channels().get(&channel_id) { - notifications::send(format!( - "{} connected and joined {}", - &msg.get_name(), - channel.name() - )); - } - - self.audio_output - .play_effect(NotificationEvents::UserConnected); + let this_channel = msg.get_channel_id(); + let other_channel = self.get_users_channel(self.server().unwrap().session_id().unwrap()); + let this_channel_name = self + .server() + .unwrap() + .channels() + .get(&this_channel) + .map(|c| c.name()) + .unwrap_or("<unnamed channel>") + .to_string(); + + if this_channel == other_channel { + notifications::send(format!( + "{} connected and joined {}", + msg.get_name(), + this_channel_name, + )); + self.push_event(MumbleEventKind::UserConnected(msg.get_name().to_string(), this_channel_name)); + self.audio_output.play_effect(NotificationEvents::UserConnected); } } } @@ -167,6 +175,7 @@ impl State { .users_mut() .get_mut(&session) .unwrap(); + let username = user.name().to_string(); let mute = if msg.has_self_mute() && user.self_mute() != msg.get_self_mute() { Some(msg.get_self_mute()) @@ -182,35 +191,43 @@ impl State { let diff = UserDiff::from(msg); user.apply_user_diff(&diff); - let user = self.server().unwrap().users().get(&session).unwrap(); if Some(session) != self.server().unwrap().session_id() { - //send notification if the user moved to or from any channel + // Send notification if the user moved either to or from our channel if let Some(to_channel) = diff.channel_id { let this_channel = self.get_users_channel(self.server().unwrap().session_id().unwrap()); - if from_channel == this_channel || to_channel == this_channel { + + if from_channel == this_channel { + // User moved from our channel to somewhere else if let Some(channel) = self.server().unwrap().channels().get(&to_channel) { + let channel = channel.name().to_string(); notifications::send(format!( "{} moved to channel {}", - user.name(), - channel.name() + &username, + &channel, )); - } else { - warn!("{} moved to invalid channel {}", user.name(), to_channel); + self.push_event(MumbleEventKind::UserLeftChannel(username.clone(), channel)); } - self.audio_output - .play_effect(if from_channel == this_channel { - NotificationEvents::UserJoinedChannel - } else { - NotificationEvents::UserLeftChannel - }); + self.audio_output.play_effect(NotificationEvents::UserLeftChannel); + } else if to_channel == this_channel { + // User moved from somewhere else to our channel + if let Some(channel) = self.server().unwrap().channels().get(&from_channel) { + let channel = channel.name().to_string(); + notifications::send(format!( + "{} moved to your channel from {}", + &username, + &channel, + )); + self.push_event(MumbleEventKind::UserJoinedChannel(username.clone(), channel)); + } + self.audio_output.play_effect(NotificationEvents::UserJoinedChannel); } } //send notification if a user muted/unmuted if mute != None || deaf != None { - let mut s = user.name().to_string(); + let mut s = username; if let Some(mute) = mute { s += if mute { " muted" } else { " unmuted" }; } @@ -221,7 +238,8 @@ impl State { s += if deaf { " deafened" } else { " undeafened" }; } s += " themselves"; - notifications::send(s); + notifications::send(s.clone()); + self.push_event(MumbleEventKind::UserMuteStateChanged(s)); } } } @@ -235,11 +253,25 @@ impl State { let this_channel = self.get_users_channel(self.server().unwrap().session_id().unwrap()); let other_channel = self.get_users_channel(msg.get_session()); if this_channel == other_channel { - self.audio_output - .play_effect(NotificationEvents::UserDisconnected); - if let Some(user) = self.server().unwrap().users().get(&msg.get_session()) { - notifications::send(format!("{} disconnected", &user.name())); - } + let channel_name = self + .server() + .unwrap() + .channels() + .get(&this_channel) + .map(|c| c.name()) + .unwrap_or("<unnamed channel>") + .to_string(); + let user_name = self + .server() + .unwrap() + .users() + .get(&msg.get_session()) + .map(|u| u.name()) + .unwrap_or("<unknown user>") + .to_string(); + notifications::send(format!("{} disconnected", &user_name)); + self.push_event(MumbleEventKind::UserDisconnected(user_name, channel_name)); + self.audio_output.play_effect(NotificationEvents::UserDisconnected); } self.server_mut() @@ -268,7 +300,7 @@ impl State { } pub fn register_message(&mut self, msg: (String, u32)) { - self.message_buffer.push(msg); + self.message_buffer.push((chrono::Local::now().naive_local(), msg.0, msg.1)); } pub fn broadcast_phase(&self, phase: StatePhase) { @@ -281,6 +313,11 @@ impl State { .play_effect(NotificationEvents::ServerConnect); } + /// Store a new event + pub fn push_event(&mut self, kind: MumbleEventKind) { + self.events.push(MumbleEvent { timestamp: chrono::Local::now().naive_local(), kind }); + } + pub fn audio_input(&self) -> &AudioInput { &self.audio_input } @@ -420,6 +457,19 @@ pub fn handle_command( new_deaf.map(|b| CommandResponse::DeafenStatus { is_deafened: b }) )) } + Command::Events { block } => { + if block { + warn!("Blocking event list is unimplemented"); + now!(Err(Error::Unimplemented)) + } else { + let events: Vec<_> = state + .events + .iter() + .map(|event| Ok(Some(CommandResponse::Event { event: event.clone() }))) + .collect(); + ExecutionContext::Now(Box::new(move || Box::new(events.into_iter()))) + } + } Command::InputVolumeSet(volume) => { state.audio_input.set_volume(volume); now!(Ok(None)) @@ -557,8 +607,9 @@ pub fn handle_command( accept_invalid_cert, ))) .unwrap(); + let state = Arc::clone(&og_state); at!( - TcpEvent::Connected => |res| { + TcpEvent::Connected => move |res| { //runs the closure when the client is connected if let TcpEventData::Connected(res) = res { Box::new(iter::once(res.map(|msg| { @@ -568,6 +619,7 @@ pub fn handle_command( } else { None }, + server_state: state.read().unwrap().server.as_ref().unwrap().into(), }) }))) } else { @@ -608,12 +660,12 @@ pub fn handle_command( }), Box::new(move |pong| { Ok(pong.map(|pong| { - (CommandResponse::ServerStatus { + CommandResponse::ServerStatus { version: pong.version, users: pong.users, max_users: pong.max_users, bandwidth: pong.bandwidth, - }) + } })) }), ), @@ -657,6 +709,7 @@ pub fn handle_command( Box::new(move |data, sender| { if let TcpEventData::TextMessage(a) = data { let message = ( + chrono::Local::now().naive_local(), a.get_message().to_owned(), ref_state .read() @@ -676,7 +729,7 @@ pub fn handle_command( let messages = std::mem::take(&mut state.message_buffer); let messages: Vec<_> = messages .into_iter() - .map(|(msg, user)| (msg, state.get_user_name(user).unwrap())) + .map(|(timestamp, msg, user)| (timestamp, msg, state.get_user_name(user).unwrap())) .map(|e| Ok(Some(CommandResponse::PastMessage { message: e }))) .collect(); @@ -692,43 +745,45 @@ pub fn handle_command( msg.set_message(message); - for target in targets { - match target { - MessageTarget::Channel { recursive, name } => { - let channel_id = state.server().unwrap().channel_name(&name); - - let channel_id = match channel_id { - Ok(id) => id, + match targets { + MessageTarget::Channel(channels) => for (channel, recursive) in channels { + let channel_id = if let ChannelTarget::Named(name) = channel { + let channel = state.server().unwrap().channel_name(&name); + match channel { + Ok(channel) => channel.0, Err(e) => return now!(Err(Error::ChannelIdentifierError(name, e))), } - .0; - - if recursive { - msg.mut_tree_id() - } else { - msg.mut_channel_id() + } else { + match state.server().unwrap().current_channel() { + Some(channel) => channel.0, + None => return now!(Err(Error::NotConnectedToChannel)), } - .push(channel_id); - } - MessageTarget::User { name } => { - let id = state - .server() - .unwrap() - .users() - .iter() - .find(|(_, user)| user.name() == &name) - .map(|(e, _)| *e); - - let id = match id { - Some(id) => id, - None => return now!(Err(Error::InvalidUsername(name))), - }; - - msg.mut_session().push(id); - } + }; + + let ids = if recursive { + msg.mut_tree_id() + } else { + msg.mut_channel_id() + }; + ids.push(channel_id); + } + MessageTarget::User(names) => for name in names { + let id = state + .server() + .unwrap() + .users() + .iter() + .find(|(_, user)| user.name() == &name) + .map(|(e, _)| *e); + + let id = match id { + Some(id) => id, + None => return now!(Err(Error::InvalidUsername(name))), + }; + + msg.mut_session().push(id); } } - packet_sender.send(msg.into()).unwrap(); now!(Ok(None)) |
