aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustav Sörnäs <gustav@sornas.net>2020-10-29 21:27:48 +0100
committerGustav Sörnäs <gustav@sornas.net>2020-10-29 21:27:48 +0100
commit3e7e375e65760a03b6692106ab0ed806ca65e470 (patch)
treeca30f277a9a81e2920c2637a7ca824ec711c8b6e
parent7120ef134c952781ab6a6d23b6be390f915372f5 (diff)
parent69ec88d3fc2e3762cf596bbf0226b204ba35d874 (diff)
downloadmum-3e7e375e65760a03b6692106ab0ed806ca65e470.tar.gz
Merge branch 'libnotify' into main
-rw-r--r--Cargo.lock105
-rw-r--r--mumd/Cargo.toml1
-rw-r--r--mumd/src/main.rs2
-rw-r--r--mumd/src/network/tcp.rs13
-rw-r--r--mumd/src/notify.rs19
-rw-r--r--mumd/src/state.rs113
-rw-r--r--mumd/src/state/user.rs12
7 files changed, 234 insertions, 31 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cb9b693..806bc91 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -420,6 +420,33 @@ dependencies = [
]
[[package]]
+name = "gdk-pixbuf"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16160d212ae91abe9f3324c3fb233929ba322dde63585d15cda3336f8c529ed1"
+dependencies = [
+ "gdk-pixbuf-sys",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+]
+
+[[package]]
+name = "gdk-pixbuf-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "798f97101eea8180da363d0e80e07ec7ec6d1809306601c0100c1de5bc8b4f52"
+dependencies = [
+ "bitflags",
+ "gio-sys",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
name = "getrandom"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -431,12 +458,61 @@ dependencies = [
]
[[package]]
+name = "gio-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a303bbf7a5e75ab3b627117ff10e495d1b9e97e1d68966285ac2b1f6270091bc"
+dependencies = [
+ "bitflags",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
+name = "glib"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9b0452824cc63066940f01adc721804919f0b76cdba3cfab977b00b87f16d4a"
+dependencies = [
+ "bitflags",
+ "glib-sys",
+ "gobject-sys",
+ "lazy_static",
+ "libc",
+]
+
+[[package]]
+name = "glib-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9693049613ff52b93013cc3d2590366d8e530366d288438724b73f6c7dc4be8"
+dependencies = [
+ "bitflags",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
+name = "gobject-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60d507c87a71b1143c66ed21a969be9b99a76df234b342d733e787e6c9c7d7c2"
+dependencies = [
+ "bitflags",
+ "glib-sys",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
name = "hermit-abi"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -520,6 +596,34 @@ dependencies = [
]
[[package]]
+name = "libnotify"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10506a4f8bc6f8f7ccc6fde3a8290378d7aed3d1a26dca606a73e2ffe140cc2d"
+dependencies = [
+ "gdk-pixbuf",
+ "gdk-pixbuf-sys",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "libnotify-sys",
+]
+
+[[package]]
+name = "libnotify-sys"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0a716b9b7d24ed10f1eb431e1527fa13c9a4bf2d4fa68bb3e54da1d0747383c"
+dependencies = [
+ "bitflags",
+ "gdk-pixbuf-sys",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
name = "lock_api"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -657,6 +761,7 @@ dependencies = [
"futures",
"futures-util",
"ipc-channel",
+ "libnotify",
"log",
"mumble-protocol",
"mumlib",
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 {