diff options
Diffstat (limited to 'mumd/src/state.rs')
| -rw-r--r-- | mumd/src/state.rs | 64 |
1 files changed, 51 insertions, 13 deletions
diff --git a/mumd/src/state.rs b/mumd/src/state.rs index cd266d7..8689a9a 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -1,23 +1,33 @@ use log::*; use crate::audio::Audio; -use crate::command::Command; +use crate::command::{Command, CommandResponse}; +use crate::network::ConnectionInfo; use mumble_protocol::control::msgs; use mumble_protocol::control::ControlPacket; use mumble_protocol::voice::Serverbound; use std::collections::HashMap; use std::collections::hash_map::Entry; +use std::net::ToSocketAddrs; use tokio::sync::{mpsc, watch}; +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum StatePhase { + Disconnected, + Connecting, + Connected, +} + pub struct State { server: Server, audio: Audio, packet_sender: mpsc::UnboundedSender<ControlPacket<Serverbound>>, command_sender: mpsc::UnboundedSender<Command>, + connection_info_sender: watch::Sender<Option<ConnectionInfo>>, - initialized_watcher: (watch::Sender<bool>, watch::Receiver<bool>), + phase_watcher: (watch::Sender<StatePhase>, watch::Receiver<StatePhase>), - username: String, + username: Option<String>, session_id: Option<u32>, } @@ -25,6 +35,7 @@ impl State { pub fn new( packet_sender: mpsc::UnboundedSender<ControlPacket<Serverbound>>, command_sender: mpsc::UnboundedSender<Command>, + connection_info_sender: watch::Sender<Option<ConnectionInfo>>, username: String, ) -> Self { Self { @@ -32,26 +43,50 @@ impl State { audio: Audio::new(), packet_sender, command_sender, - initialized_watcher: watch::channel(false), - username, + connection_info_sender, + phase_watcher: watch::channel(StatePhase::Disconnected), + username: None, session_id: None, } } - //TODO result - pub async fn handle_command(&mut self, command: Command) { + pub async fn handle_command(&mut self, command: Command) -> Result<Option<CommandResponse>, ()> { match command { Command::ChannelJoin{channel_id} => { if self.session_id.is_none() { warn!("Tried to join channel but we don't have a session id"); - return; + return Err(()); } let mut msg = msgs::UserState::new(); msg.set_session(self.session_id.unwrap()); msg.set_channel_id(channel_id); self.packet_sender.send(msg.into()).unwrap(); + Ok(None) + } + Command::ChannelList => { + Ok(Some(CommandResponse::ChannelList{channels: self.server.channels.clone()})) + } + Command::ServerConnect{host, port, username, accept_invalid_cert} => { + if !matches!(*self.phase_receiver().borrow(), StatePhase::Disconnected) { + warn!("Tried to connect to a server while already connected"); + return Err(()); + } + self.username = Some(username); + self.phase_watcher.0.broadcast(StatePhase::Connecting).unwrap(); + let socket_addr = (host.as_ref(), port) + .to_socket_addrs() + .expect("Failed to parse server address") + .next() + .expect("Failed to resolve server address"); + self.connection_info_sender.broadcast(Some(ConnectionInfo::new( + socket_addr, + host, + accept_invalid_cert, + ))); + while !matches!(self.phase_receiver().recv().await.unwrap(), StatePhase::Connected) {} + Ok(None) } - _ => {} + _ => { Ok(None) } } } @@ -63,7 +98,7 @@ impl State { if !msg.has_name() { warn!("Missing name in initial user state"); } else { - if msg.get_name() == self.username { + if msg.get_name() == self.username.as_ref().unwrap() { match self.session_id { None => { debug!("Found our session id: {}", msg.get_session()); @@ -85,17 +120,18 @@ impl State { } pub fn initialized(&self) { - self.initialized_watcher.0.broadcast(true).unwrap(); + self.phase_watcher.0.broadcast(StatePhase::Connected).unwrap(); } pub fn audio(&self) -> &Audio { &self.audio } pub fn audio_mut(&mut self) -> &mut Audio { &mut self.audio } pub fn packet_sender(&self) -> mpsc::UnboundedSender<ControlPacket<Serverbound>> { self.packet_sender.clone() } - pub fn initialized_receiver(&self) -> watch::Receiver<bool> { self.initialized_watcher.1.clone() } + pub fn phase_receiver(&self) -> watch::Receiver<StatePhase> { self.phase_watcher.1.clone() } pub fn server_mut(&mut self) -> &mut Server { &mut self.server } - pub fn username(&self) -> &str { &self.username } + pub fn username(&self) -> Option<&String> { self.username.as_ref() } } +#[derive(Debug)] pub struct Server { channels: HashMap<u32, Channel>, users: HashMap<u32, User>, @@ -159,6 +195,7 @@ impl Server { } } +#[derive(Clone, Debug)] pub struct Channel { description: Option<String>, links: Vec<u32>, @@ -212,6 +249,7 @@ impl Channel { } } +#[derive(Debug)] pub struct User { channel: u32, comment: Option<String>, |
