diff options
Diffstat (limited to 'mumd/src')
| -rw-r--r-- | mumd/src/audio.rs | 11 | ||||
| -rw-r--r-- | mumd/src/audio/input.rs | 16 | ||||
| -rw-r--r-- | mumd/src/audio/output.rs | 18 | ||||
| -rw-r--r-- | mumd/src/audio/transformers.rs | 1 | ||||
| -rw-r--r-- | mumd/src/client.rs | 2 | ||||
| -rw-r--r-- | mumd/src/error.rs | 6 | ||||
| -rw-r--r-- | mumd/src/main.rs | 43 | ||||
| -rw-r--r-- | mumd/src/network.rs | 4 | ||||
| -rw-r--r-- | mumd/src/network/tcp.rs | 41 | ||||
| -rw-r--r-- | mumd/src/network/udp.rs | 19 | ||||
| -rw-r--r-- | mumd/src/state.rs | 43 | ||||
| -rw-r--r-- | mumd/src/state/server.rs | 2 | ||||
| -rw-r--r-- | mumd/src/state/user.rs | 2 |
13 files changed, 142 insertions, 66 deletions
diff --git a/mumd/src/audio.rs b/mumd/src/audio.rs index fb22b44..bbaf2e1 100644 --- a/mumd/src/audio.rs +++ b/mumd/src/audio.rs @@ -17,6 +17,7 @@ use mumble_protocol::voice::{VoicePacket, VoicePacketPayload}; use mumble_protocol::Serverbound; use mumlib::config::SoundEffect; use std::collections::{hash_map::Entry, HashMap}; +use std::fmt::Debug; use std::sync::{Arc, Mutex}; use tokio::sync::watch; @@ -77,6 +78,16 @@ impl AudioInput { } } +impl Debug for AudioInput { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("AudioInput") + .field("device", &self.device) + .field("channel_receiver", &"receiver") + .finish() + } +} + +#[derive(Debug)] /// Audio output state. The audio is received from each client over the network, /// decoded, merged and finally played to an [AudioOutputDevice] (e.g. speaker, /// headphones, ...). diff --git a/mumd/src/audio/input.rs b/mumd/src/audio/input.rs index 37ea60a..4dfc465 100644 --- a/mumd/src/audio/input.rs +++ b/mumd/src/audio/input.rs @@ -2,6 +2,7 @@ use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use cpal::{InputCallbackInfo, Sample, SampleFormat, SampleRate, StreamConfig}; use log::*; +use std::fmt::Debug; use tokio::sync::watch; use crate::audio::SAMPLE_RATE; @@ -171,13 +172,13 @@ impl AudioInputDevice for DefaultAudioInputDevice { fn play(&self) -> Result<(), AudioError> { self.stream .play() - .map_err(|e| AudioError::InputPlayError(e)) + .map_err(AudioError::InputPlayError) } fn pause(&self) -> Result<(), AudioError> { self.stream .pause() - .map_err(|e| AudioError::InputPauseError(e)) + .map_err(AudioError::InputPauseError) } fn set_volume(&self, volume: f32) { @@ -192,3 +193,14 @@ impl AudioInputDevice for DefaultAudioInputDevice { self.channels as usize } } + +impl Debug for DefaultAudioInputDevice { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("DefaultAudioInputDevice") + .field("sample_receiver", &self.sample_receiver) + .field("channels", &self.channels) + .field("volume_sender", &self.volume_sender) + .field("stream", &"cpal::Stream") + .finish() + } +} diff --git a/mumd/src/audio/output.rs b/mumd/src/audio/output.rs index 6aa67dd..980e65f 100644 --- a/mumd/src/audio/output.rs +++ b/mumd/src/audio/output.rs @@ -11,6 +11,7 @@ use dasp_ring_buffer::Bounded; use log::*; use mumble_protocol::voice::VoicePacketPayload; use std::collections::{HashMap, VecDeque}; +use std::fmt::Debug; use std::iter; use std::ops::AddAssign; use std::sync::{Arc, Mutex}; @@ -19,6 +20,7 @@ use tokio::sync::watch; type ClientStreamKey = (VoiceStreamType, u32); /// State for decoding audio received from another user. +#[derive(Debug)] pub struct ClientAudioData { buf: Bounded<Vec<f32>>, output_channels: opus::Channels, @@ -66,6 +68,7 @@ impl ClientAudioData { } /// Collected state for client opus decoders and sound effects. +#[derive(Debug)] pub struct ClientStream { buffer_clients: HashMap<ClientStreamKey, ClientAudioData>, buffer_effects: VecDeque<f32>, @@ -243,13 +246,13 @@ impl AudioOutputDevice for DefaultAudioOutputDevice { fn play(&self) -> Result<(), AudioError> { self.stream .play() - .map_err(|e| AudioError::OutputPlayError(e)) + .map_err(AudioError::OutputPlayError) } fn pause(&self) -> Result<(), AudioError> { self.stream .pause() - .map_err(|e| AudioError::OutputPauseError(e)) + .map_err(AudioError::OutputPauseError) } fn set_volume(&self, volume: f32) { @@ -298,3 +301,14 @@ pub fn callback<T: Sample + AddAssign + SaturatingAdd + std::fmt::Display>( } } } + +impl Debug for DefaultAudioOutputDevice { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("DefaultAudioInputDevice") + .field("client_streams", &self.client_streams) + .field("config", &self.config) + .field("volume_sender", &self.volume_sender) + .field("stream", &"cpal::Stream") + .finish() + } +} diff --git a/mumd/src/audio/transformers.rs b/mumd/src/audio/transformers.rs index 91cf3ac..21a71b5 100644 --- a/mumd/src/audio/transformers.rs +++ b/mumd/src/audio/transformers.rs @@ -6,6 +6,7 @@ pub trait Transformer { } /// A struct representing a noise gate transform. +#[derive(Debug)] pub struct NoiseGate { alltime_high: f32, open: usize, diff --git a/mumd/src/client.rs b/mumd/src/client.rs index 9e8ca18..753583f 100644 --- a/mumd/src/client.rs +++ b/mumd/src/client.rs @@ -33,7 +33,7 @@ pub async fn handle( packet_sender.clone(), packet_receiver, event_queue.clone(), - ).fuse() => r.map_err(|e| ClientError::TcpError(e)), + ).fuse() => r.map_err(ClientError::TcpError), _ = udp::handle( Arc::clone(&state), connection_info_receiver.clone(), diff --git a/mumd/src/error.rs b/mumd/src/error.rs index da1bdd3..4277d7f 100644 --- a/mumd/src/error.rs +++ b/mumd/src/error.rs @@ -5,6 +5,7 @@ use tokio::sync::mpsc; pub type ServerSendError = mpsc::error::SendError<ControlPacket<Serverbound>>; +#[derive(Debug)] pub enum TcpError { NoConnectionInfoReceived, TlsConnectorBuilderError(native_tls::Error), @@ -40,6 +41,7 @@ impl From<ServerSendError> for TcpError { } } +#[derive(Debug)] pub enum UdpError { NoConnectionInfoReceived, DisconnectBeforeCryptSetup, @@ -53,6 +55,7 @@ impl From<std::io::Error> for UdpError { } } +#[derive(Debug)] pub enum ClientError { TcpError(TcpError), } @@ -65,6 +68,7 @@ impl fmt::Display for ClientError { } } +#[derive(Debug)] pub enum AudioStream { Input, Output, @@ -79,6 +83,7 @@ impl fmt::Display for AudioStream { } } +#[derive(Debug)] pub enum AudioError { NoDevice(AudioStream), NoConfigs(AudioStream, cpal::SupportedStreamConfigsError), @@ -105,6 +110,7 @@ impl fmt::Display for AudioError { } } +#[derive(Debug)] pub enum StateError { AudioError(AudioError), ConfigError(ConfigError), diff --git a/mumd/src/main.rs b/mumd/src/main.rs index bc72779..479c568 100644 --- a/mumd/src/main.rs +++ b/mumd/src/main.rs @@ -1,10 +1,25 @@ -mod audio; -mod client; -mod command; -mod error; -mod network; -mod notifications; -mod state; +#![warn(elided_lifetimes_in_paths)] +#![warn(meta_variable_misuse)] +#![warn(missing_debug_implementations)] +#![warn(single_use_lifetimes)] +#![warn(unreachable_pub)] +#![warn(unused_crate_dependencies)] +#![warn(unused_import_braces)] +#![warn(unused_lifetimes)] +#![warn(unused_qualifications)] +#![deny(macro_use_extern_crate)] +#![deny(missing_abi)] +#![deny(future_incompatible)] +#![forbid(unsafe_code)] +#![forbid(non_ascii_idents)] + +pub mod audio; +pub mod client; +pub mod command; +pub mod error; +pub mod network; +pub mod notifications; +pub mod state; use crate::state::State; @@ -22,10 +37,7 @@ use tokio_util::codec::{FramedRead, FramedWrite, LengthDelimitedCodec}; #[tokio::main] async fn main() { - if std::env::args() - .find(|s| s.as_str() == "--version") - .is_some() - { + if std::env::args().any(|s| s.as_str() == "--version") { println!("mumd {}", env!("VERSION")); return; } @@ -79,12 +91,9 @@ async fn main() { _ = receive_commands(command_sender).fuse() => Ok(()), }; - match run { - Err(e) => { - error!("mumd: {}", e); - std::process::exit(1); - } - _ => {} + if let Err(e) = run { + error!("mumd: {}", e); + std::process::exit(1); } } diff --git a/mumd/src/network.rs b/mumd/src/network.rs index 2b803c0..1066fef 100644 --- a/mumd/src/network.rs +++ b/mumd/src/network.rs @@ -30,8 +30,8 @@ impl ConnectionInfo { #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] pub enum VoiceStreamType { - TCP, - UDP, + Tcp, + Udp, } async fn run_until<F, R>( diff --git a/mumd/src/network/tcp.rs b/mumd/src/network/tcp.rs index f620a32..0fdc4c5 100644 --- a/mumd/src/network/tcp.rs +++ b/mumd/src/network/tcp.rs @@ -14,6 +14,7 @@ use mumble_protocol::{Clientbound, Serverbound}; use mumlib::command::MumbleEventKind; use std::collections::HashMap; use std::convert::{Into, TryInto}; +use std::fmt::Debug; use std::net::SocketAddr; use std::sync::{Arc, RwLock}; use tokio::net::TcpStream; @@ -31,8 +32,8 @@ type TcpSender = SplitSink< type TcpReceiver = SplitStream<Framed<TlsStream<TcpStream>, ControlCodec<Serverbound, Clientbound>>>; -pub(crate) type TcpEventCallback = Box<dyn FnOnce(TcpEventData)>; -pub(crate) type TcpEventSubscriber = Box<dyn FnMut(TcpEventData) -> bool>; //the bool indicates if it should be kept or not +pub(crate) type TcpEventCallback = Box<dyn FnOnce(TcpEventData<'_>)>; +pub(crate) type TcpEventSubscriber = Box<dyn FnMut(TcpEventData<'_>) -> bool>; //the bool indicates if it should be kept or not /// Why the TCP was disconnected. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] @@ -57,15 +58,15 @@ pub enum TcpEvent { /// Having two different types might feel a bit confusing. Essentially, a /// callback _registers_ to a [TcpEvent] but _takes_ a [TcpEventData] as /// parameter. -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum TcpEventData<'a> { Connected(Result<&'a msgs::ServerSync, mumlib::Error>), Disconnected(DisconnectedReason), TextMessage(&'a msgs::TextMessage), } -impl<'a> From<&TcpEventData<'a>> for TcpEvent { - fn from(t: &TcpEventData) -> Self { +impl From<&TcpEventData<'_>> for TcpEvent { + fn from(t: &TcpEventData<'_>) -> Self { match t { TcpEventData::Connected(_) => TcpEvent::Connected, TcpEventData::Disconnected(reason) => TcpEvent::Disconnected(*reason), @@ -74,7 +75,7 @@ impl<'a> From<&TcpEventData<'a>> for TcpEvent { } } -#[derive(Clone)] +#[derive(Clone, Default)] pub struct TcpEventQueue { callbacks: Arc<RwLock<HashMap<TcpEvent, Vec<TcpEventCallback>>>>, subscribers: Arc<RwLock<HashMap<TcpEvent, Vec<TcpEventSubscriber>>>>, @@ -111,7 +112,7 @@ impl TcpEventQueue { /// Fires all callbacks related to a specific TCP event and removes them from the event queue. /// Also calls all event subscribers, but keeps them in the queue - pub fn resolve<'a>(&self, data: TcpEventData<'a>) { + pub fn resolve(&self, data: TcpEventData<'_>) { if let Some(vec) = self .callbacks .write() @@ -139,6 +140,13 @@ impl TcpEventQueue { } } +impl Debug for TcpEventQueue { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TcpEventQueue") + .finish() + } +} + pub async fn handle( state: Arc<RwLock<State>>, mut connection_info_receiver: watch::Receiver<Option<ConnectionInfo>>, @@ -148,13 +156,14 @@ pub async fn handle( event_queue: TcpEventQueue, ) -> Result<(), TcpError> { loop { - let connection_info = 'data: loop { - while connection_info_receiver.changed().await.is_ok() { + let connection_info = loop { + if connection_info_receiver.changed().await.is_ok() { if let Some(data) = connection_info_receiver.borrow().clone() { - break 'data data; + break data; } + } else { + return Err(TcpError::NoConnectionInfoReceived); } - return Err(TcpError::NoConnectionInfoReceived); }; let connect_result = connect( connection_info.socket_addr, @@ -242,12 +251,12 @@ async fn connect( builder.danger_accept_invalid_certs(accept_invalid_cert); let connector: TlsConnector = builder .build() - .map_err(|e| TcpError::TlsConnectorBuilderError(e))? + .map_err(TcpError::TlsConnectorBuilderError)? .into(); let tls_stream = connector .connect(&server_host, stream) .await - .map_err(|e| TcpError::TlsConnectError(e))?; + .map_err(TcpError::TlsConnectError)?; debug!("TLS connected"); // Wrap the TLS stream with Mumble's client-side control-channel codec @@ -304,13 +313,13 @@ async fn send_voice( inner_phase_watcher.changed().await.unwrap(); if matches!( *inner_phase_watcher.borrow(), - StatePhase::Connected(VoiceStreamType::TCP) + StatePhase::Connected(VoiceStreamType::Tcp) ) { break; } } run_until( - |phase| !matches!(phase, StatePhase::Connected(VoiceStreamType::TCP)), + |phase| !matches!(phase, StatePhase::Connected(VoiceStreamType::Tcp)), async { loop { packet_sender.send( @@ -465,7 +474,7 @@ async fn listen( .. } => { state.read().unwrap().audio_output().decode_packet_payload( - VoiceStreamType::TCP, + VoiceStreamType::Tcp, session_id, payload, ); diff --git a/mumd/src/network/udp.rs b/mumd/src/network/udp.rs index 95dcf33..0f78638 100644 --- a/mumd/src/network/udp.rs +++ b/mumd/src/network/udp.rs @@ -37,13 +37,14 @@ pub async fn handle( let receiver = state.read().unwrap().audio_input().receiver(); loop { - let connection_info = 'data: loop { - while connection_info_receiver.changed().await.is_ok() { + let connection_info = loop { + if connection_info_receiver.changed().await.is_ok() { if let Some(data) = connection_info_receiver.borrow().clone() { - break 'data data; + break data; } + } else { + return Err(UdpError::NoConnectionInfoReceived); } - return Err(UdpError::NoConnectionInfoReceived); }; let (sink, source) = connect(&mut crypt_state_receiver).await?; @@ -136,7 +137,7 @@ async fn listen( state .read() .unwrap() - .broadcast_phase(StatePhase::Connected(VoiceStreamType::UDP)); + .broadcast_phase(StatePhase::Connected(VoiceStreamType::Udp)); last_ping_recv.store(timestamp, Ordering::Relaxed); } VoicePacket::Audio { @@ -147,7 +148,7 @@ async fn listen( .. } => { state.read().unwrap().audio_output().decode_packet_payload( - VoiceStreamType::UDP, + VoiceStreamType::Udp, session_id, payload, ); @@ -173,7 +174,7 @@ async fn send_pings( state .read() .unwrap() - .broadcast_phase(StatePhase::Connected(VoiceStreamType::TCP)); + .broadcast_phase(StatePhase::Connected(VoiceStreamType::Tcp)); } match sink .lock() @@ -208,13 +209,13 @@ async fn send_voice( inner_phase_watcher.changed().await.unwrap(); if matches!( *inner_phase_watcher.borrow(), - StatePhase::Connected(VoiceStreamType::UDP) + StatePhase::Connected(VoiceStreamType::Udp) ) { break; } } run_until( - |phase| !matches!(phase, StatePhase::Connected(VoiceStreamType::UDP)), + |phase| !matches!(phase, StatePhase::Connected(VoiceStreamType::Udp)), async { let mut receiver = receiver.lock().await; loop { diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 8512715..ba461fd 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -18,6 +18,7 @@ use mumble_protocol::voice::Serverbound; use mumlib::command::{ChannelTarget, Command, CommandResponse, MessageTarget, MumbleEvent, MumbleEventKind}; use mumlib::config::Config; use mumlib::Error; +use std::fmt::Debug; use std::iter; use std::net::{SocketAddr, ToSocketAddrs}; use std::sync::{Arc, RwLock}; @@ -26,7 +27,7 @@ use tokio::sync::{mpsc, watch}; macro_rules! at { ( $( $event:expr => $generator:expr ),+ $(,)? ) => { ExecutionContext::TcpEventCallback(vec![ - $( ($event, Box::new($generator)), )* + $( ($event, Box::new($generator)), )+ ]) }; } @@ -39,18 +40,18 @@ macro_rules! now { type Responses = Box<dyn Iterator<Item = mumlib::error::Result<Option<CommandResponse>>>>; +type TcpEventCallback = Box<dyn FnOnce(TcpEventData<'_>) -> Responses>; +type TcpEventSubscriberCallback = Box< + dyn FnMut( + TcpEventData<'_>, + &mut mpsc::UnboundedSender<mumlib::error::Result<Option<CommandResponse>>>, + ) -> bool +>; + //TODO give me a better name pub enum ExecutionContext { - TcpEventCallback(Vec<(TcpEvent, Box<dyn FnOnce(TcpEventData) -> Responses>)>), - TcpEventSubscriber( - TcpEvent, - Box< - dyn FnMut( - TcpEventData, - &mut mpsc::UnboundedSender<mumlib::error::Result<Option<CommandResponse>>>, - ) -> bool, - >, - ), + TcpEventCallback(Vec<(TcpEvent, TcpEventCallback)>), + TcpEventSubscriber(TcpEvent, TcpEventSubscriberCallback), Now(Box<dyn FnOnce() -> Responses>), Ping( Box<dyn FnOnce() -> mumlib::error::Result<SocketAddr>>, @@ -60,6 +61,17 @@ pub enum ExecutionContext { ), } +impl Debug for ExecutionContext { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple(match self { + ExecutionContext::TcpEventCallback(_) => "TcpEventCallback", + ExecutionContext::TcpEventSubscriber(_, _) => "TcpEventSubscriber", + ExecutionContext::Now(_) => "Now", + ExecutionContext::Ping(_, _) => "Ping", + }).finish() + } +} + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum StatePhase { Disconnected, @@ -67,6 +79,7 @@ pub enum StatePhase { Connected(VoiceStreamType), } +#[derive(Debug)] pub struct State { config: Config, server: Option<Server>, @@ -87,9 +100,9 @@ impl State { config.audio.input_volume.unwrap_or(1.0), phase_watcher.1.clone(), ) - .map_err(|e| StateError::AudioError(e))?; + .map_err(StateError::AudioError)?; let audio_output = AudioOutput::new(config.audio.output_volume.unwrap_or(1.0)) - .map_err(|e| StateError::AudioError(e))?; + .map_err(StateError::AudioError)?; let mut state = Self { config, server: None, @@ -305,7 +318,7 @@ impl State { } pub fn initialized(&self) { - self.broadcast_phase(StatePhase::Connected(VoiceStreamType::TCP)); + self.broadcast_phase(StatePhase::Connected(VoiceStreamType::Tcp)); self.audio_output .play_effect(NotificationEvents::ServerConnect); } @@ -770,7 +783,7 @@ pub fn handle_command( .unwrap() .users() .iter() - .find(|(_, user)| user.name() == &name) + .find(|(_, user)| user.name() == name) .map(|(e, _)| *e); let id = match id { diff --git a/mumd/src/state/server.rs b/mumd/src/state/server.rs index 4abde49..5d49457 100644 --- a/mumd/src/state/server.rs +++ b/mumd/src/state/server.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use std::collections::hash_map::Entry; use std::collections::HashMap; -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Server { channels: HashMap<u32, Channel>, users: HashMap<u32, User>, diff --git a/mumd/src/state/user.rs b/mumd/src/state/user.rs index 5770bca..0ffde90 100644 --- a/mumd/src/state/user.rs +++ b/mumd/src/state/user.rs @@ -78,7 +78,7 @@ impl User { } } - pub fn apply_user_diff(&mut self, diff: &crate::state::user::UserDiff) { + pub fn apply_user_diff(&mut self, diff: &UserDiff) { if let Some(comment) = diff.comment.clone() { self.comment = Some(comment); } |
