aboutsummaryrefslogtreecommitdiffstats
path: root/mumd/src
diff options
context:
space:
mode:
authorGustav Sörnäs <gustav@sornas.net>2020-11-28 02:46:10 +0100
committerGustav Sörnäs <gustav@sornas.net>2020-11-28 02:46:10 +0100
commit1014f6c85b3d77009d8ee34f9517c73fc32f5379 (patch)
tree3736f150813671ef0ac3aa8f2a847021ca7bb3a7 /mumd/src
parent790fdc02d071d0f110eff1b17374f315a1516fb7 (diff)
parent7f04dcfc4c04f2266f1399f238f8869c1c09b57a (diff)
downloadmum-1014f6c85b3d77009d8ee34f9517c73fc32f5379.tar.gz
Merge branch 'dont-overwrite-socket-file' into 'main'
Dont overwrite socket file Closes #72 See merge request gustav/mum!40
Diffstat (limited to 'mumd/src')
-rw-r--r--mumd/src/main.rs22
-rw-r--r--mumd/src/state.rs253
2 files changed, 149 insertions, 126 deletions
diff --git a/mumd/src/main.rs b/mumd/src/main.rs
index b83299f..db6d2ef 100644
--- a/mumd/src/main.rs
+++ b/mumd/src/main.rs
@@ -8,7 +8,7 @@ use crate::network::ConnectionInfo;
use crate::state::State;
use futures::join;
-use ipc_channel::ipc::{IpcOneShotServer, IpcSender};
+use ipc_channel::ipc::{self, IpcOneShotServer, IpcSender};
use log::*;
use mumble_protocol::control::ControlPacket;
use mumble_protocol::crypt::ClientCryptState;
@@ -25,6 +25,26 @@ async fn main() {
setup_logger(std::io::stderr(), true);
notify::init();
+ // check if another instance is live
+ let (tx_client, rx_client) =
+ ipc::channel::<mumlib::error::Result<Option<CommandResponse>>>().unwrap();
+ if let Ok(server_name) = fs::read_to_string(mumlib::SOCKET_PATH) {
+ if let Ok(tx0) = IpcSender::connect(server_name) {
+ if tx0.send((Command::Ping, tx_client)).is_ok() {
+ match rx_client.recv() {
+ Ok(Ok(Some(CommandResponse::Pong))) => {
+ error!("Another instance of mumd is already running");
+ return;
+ },
+ resp => {
+ warn!("Ping with weird response. Continuing...");
+ debug!("Response was {:?}", resp);
+ }
+ }
+ }
+ }
+ }
+
// Oneshot channel for setting UDP CryptState from control task
// For simplicity we don't deal with re-syncing, real applications would have to.
let (crypt_state_sender, crypt_state_receiver) = mpsc::channel::<ClientCryptState>(1); // crypt state should always be consumed before sending a new one
diff --git a/mumd/src/state.rs b/mumd/src/state.rs
index 36d3ee9..7a4704a 100644
--- a/mumd/src/state.rs
+++ b/mumd/src/state.rs
@@ -147,92 +147,10 @@ impl State {
);
now!(Ok(Some(CommandResponse::ChannelList { channels: list })))
}
- Command::ServerConnect {
- host,
- port,
- username,
- accept_invalid_cert,
- } => {
- if !matches!(*self.phase_receiver().borrow(), StatePhase::Disconnected) {
- return now!(Err(Error::AlreadyConnectedError));
- }
- let mut server = Server::new();
- *server.username_mut() = Some(username);
- *server.host_mut() = Some(format!("{}:{}", host, port));
- self.server = Some(server);
- self.phase_watcher
- .0
- .broadcast(StatePhase::Connecting)
- .unwrap();
-
- let socket_addr = match (host.as_ref(), port)
- .to_socket_addrs()
- .map(|mut e| e.next())
- {
- Ok(Some(v)) => v,
- _ => {
- warn!("Error parsing server addr");
- return now!(Err(Error::InvalidServerAddrError(host, port)));
- }
- };
- self.connection_info_sender
- .broadcast(Some(ConnectionInfo::new(
- socket_addr,
- host,
- accept_invalid_cert,
- )))
- .unwrap();
- at!(TcpEvent::Connected, |e| {
- //runs the closure when the client is connected
- if let TcpEventData::Connected(msg) = e {
- Ok(Some(CommandResponse::ServerConnect {
- welcome_message: if msg.has_welcome_text() {
- Some(msg.get_welcome_text().to_string())
- } else {
- None
- },
- }))
- } else {
- unreachable!("callback should be provided with a TcpEventData::Connected");
- }
- })
- }
- Command::Status => {
- if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
- return now!(Err(Error::DisconnectedError));
- }
- let state = self.server.as_ref().unwrap().into();
- now!(Ok(Some(CommandResponse::Status {
- server_state: state, //guaranteed not to panic because if we are connected, server is guaranteed to be Some
- })))
- }
- Command::ServerDisconnect => {
- if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
- return now!(Err(Error::DisconnectedError));
- }
-
- self.server = None;
- self.audio.clear_clients();
-
- self.phase_watcher
- .0
- .broadcast(StatePhase::Disconnected)
- .unwrap();
- self.audio.play_effect(NotificationEvents::ServerDisconnect);
- now!(Ok(None))
- }
Command::ConfigReload => {
self.reload_config();
now!(Ok(None))
}
- Command::InputVolumeSet(volume) => {
- self.audio.set_input_volume(volume);
- now!(Ok(None))
- }
- Command::OutputVolumeSet(volume) => {
- self.audio.set_output_volume(volume);
- now!(Ok(None))
- }
Command::DeafenSelf(toggle) => {
if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
return now!(Err(Error::DisconnectedError));
@@ -287,6 +205,45 @@ impl State {
now!(Ok(new_deaf.map(|b| CommandResponse::DeafenStatus { is_deafened: b })))
}
+ Command::InputVolumeSet(volume) => {
+ self.audio.set_input_volume(volume);
+ now!(Ok(None))
+ }
+ Command::MuteOther(string, toggle) => {
+ if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
+ return now!(Err(Error::DisconnectedError));
+ }
+
+ let id = self
+ .server_mut()
+ .unwrap()
+ .users_mut()
+ .iter_mut()
+ .find(|(_, user)| user.name() == &string);
+
+ let (id, user) = match id {
+ Some(id) => (*id.0, id.1),
+ None => return now!(Err(Error::InvalidUsernameError(string))),
+ };
+
+ let action = match toggle {
+ Some(state) => {
+ if user.suppressed() != state {
+ Some(state)
+ } else {
+ None
+ }
+ }
+ None => Some(!user.suppressed()),
+ };
+
+ if let Some(action) = action {
+ user.set_suppressed(action);
+ self.audio.set_mute(id, action);
+ }
+
+ return now!(Ok(None));
+ }
Command::MuteSelf(toggle) => {
if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
return now!(Err(Error::DisconnectedError));
@@ -342,58 +299,76 @@ impl State {
now!(Ok(new_mute.map(|b| CommandResponse::MuteStatus { is_muted: b })))
}
- Command::MuteOther(string, toggle) => {
- if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
- return now!(Err(Error::DisconnectedError));
+ Command::OutputVolumeSet(volume) => {
+ self.audio.set_output_volume(volume);
+ now!(Ok(None))
+ }
+ Command::Ping => {
+ now!(Ok(Some(CommandResponse::Pong)))
+ }
+ Command::ServerConnect {
+ host,
+ port,
+ username,
+ accept_invalid_cert,
+ } => {
+ if !matches!(*self.phase_receiver().borrow(), StatePhase::Disconnected) {
+ return now!(Err(Error::AlreadyConnectedError));
}
+ let mut server = Server::new();
+ *server.username_mut() = Some(username);
+ *server.host_mut() = Some(format!("{}:{}", host, port));
+ self.server = Some(server);
+ self.phase_watcher
+ .0
+ .broadcast(StatePhase::Connecting)
+ .unwrap();
- let id = self
- .server_mut()
- .unwrap()
- .users_mut()
- .iter_mut()
- .find(|(_, user)| user.name() == &string);
-
- let (id, user) = match id {
- Some(id) => (*id.0, id.1),
- None => return now!(Err(Error::InvalidUsernameError(string))),
- };
-
- let action = match toggle {
- Some(state) => {
- if user.suppressed() != state {
- Some(state)
- } else {
- None
- }
+ let socket_addr = match (host.as_ref(), port)
+ .to_socket_addrs()
+ .map(|mut e| e.next())
+ {
+ Ok(Some(v)) => v,
+ _ => {
+ warn!("Error parsing server addr");
+ return now!(Err(Error::InvalidServerAddrError(host, port)));
}
- None => Some(!user.suppressed()),
};
-
- if let Some(action) = action {
- user.set_suppressed(action);
- self.audio.set_mute(id, action);
- }
-
- return now!(Ok(None));
+ self.connection_info_sender
+ .broadcast(Some(ConnectionInfo::new(
+ socket_addr,
+ host,
+ accept_invalid_cert,
+ )))
+ .unwrap();
+ at!(TcpEvent::Connected, |e| {
+ //runs the closure when the client is connected
+ if let TcpEventData::Connected(msg) = e {
+ Ok(Some(CommandResponse::ServerConnect {
+ welcome_message: if msg.has_welcome_text() {
+ Some(msg.get_welcome_text().to_string())
+ } else {
+ None
+ },
+ }))
+ } else {
+ unreachable!("callback should be provided with a TcpEventData::Connected");
+ }
+ })
}
- Command::UserVolumeSet(string, volume) => {
+ Command::ServerDisconnect => {
if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
return now!(Err(Error::DisconnectedError));
}
- let user_id = match self
- .server()
- .unwrap()
- .users()
- .iter()
- .find(|e| e.1.name() == &string)
- .map(|e| *e.0)
- {
- None => return now!(Err(Error::InvalidUsernameError(string))),
- Some(v) => v,
- };
- self.audio.set_user_volume(user_id, volume);
+ self.server = None;
+ self.audio.clear_clients();
+
+ self.phase_watcher
+ .0
+ .broadcast(StatePhase::Disconnected)
+ .unwrap();
+ self.audio.play_effect(NotificationEvents::ServerDisconnect);
now!(Ok(None))
}
Command::ServerStatus { host, port } => ExecutionContext::Ping(
@@ -415,6 +390,34 @@ impl State {
}))
}),
),
+ Command::Status => {
+ if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
+ return now!(Err(Error::DisconnectedError));
+ }
+ let state = self.server.as_ref().unwrap().into();
+ now!(Ok(Some(CommandResponse::Status {
+ server_state: state, //guaranteed not to panic because if we are connected, server is guaranteed to be Some
+ })))
+ }
+ Command::UserVolumeSet(string, volume) => {
+ if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
+ return now!(Err(Error::DisconnectedError));
+ }
+ let user_id = match self
+ .server()
+ .unwrap()
+ .users()
+ .iter()
+ .find(|e| e.1.name() == &string)
+ .map(|e| *e.0)
+ {
+ None => return now!(Err(Error::InvalidUsernameError(string))),
+ Some(v) => v,
+ };
+
+ self.audio.set_user_volume(user_id, volume);
+ now!(Ok(None))
+ }
}
}