From dec60d11b81a7dbef9286ac72be36ebaec95543a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Mon, 12 Oct 2020 02:20:15 +0200 Subject: begin saving state Co-authored-by: Eskil Queseth --- mumd/src/main.rs | 12 +++- mumd/src/network.rs | 35 +++++++-- mumd/src/state.rs | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++ todo.org | 5 +- 4 files changed, 246 insertions(+), 7 deletions(-) create mode 100644 mumd/src/state.rs diff --git a/mumd/src/main.rs b/mumd/src/main.rs index 1608947..afc1b2e 100644 --- a/mumd/src/main.rs +++ b/mumd/src/main.rs @@ -1,6 +1,9 @@ mod audio; mod network; +mod command; +mod state; use crate::audio::Audio; +use crate::state::Server; use argparse::ArgumentParser; use argparse::Store; @@ -51,9 +54,12 @@ async fn main() { audio.output_stream.play().unwrap(); let audio = Arc::new(Mutex::new(audio)); + let server_state = Arc::new(Mutex::new(Server::new())); + // Run it join!( network::handle_tcp( + server_state, server_addr, server_host, username, @@ -61,6 +67,10 @@ async fn main() { crypt_state_sender, Arc::clone(&audio), ), - network::handle_udp(server_addr, crypt_state_receiver, audio,), + network::handle_udp( + server_addr, + crypt_state_receiver, + audio, + ), ); } diff --git a/mumd/src/network.rs b/mumd/src/network.rs index 8d9b0a1..cd36f21 100644 --- a/mumd/src/network.rs +++ b/mumd/src/network.rs @@ -1,4 +1,5 @@ use crate::audio::Audio; +use crate::state::Server; use bytes::Bytes; use futures::channel::oneshot; @@ -102,6 +103,7 @@ async fn authenticate(sink: Arc>, username: String) { } async fn listen_tcp( + server: Arc>, sink: Arc>, mut stream: TcpReceiver, crypt_state_sender: oneshot::Sender, @@ -141,33 +143,58 @@ async fn listen_tcp( .expect("Server sent server_nonce with incorrect size"), )); } - ControlPacket::ServerSync(_) => { + ControlPacket::ServerSync(msg) => { println!("Logged in!"); if let Some(sender) = crypt_state_sender.take() { - let _ = sender.send( + sender.send( crypt_state .take() .expect("Server didn't send us any CryptSetup packet!"), ); } + let mut server = server.lock().unwrap(); + server.parse_server_sync(msg); + match &server.welcome_text { + Some(s) => println!("Welcome: {}", s), + None => println!("No welcome found"), + } + for (_, channel) in server.channels() { + println!("Found channel {}", channel.name()); + } + sink.lock().unwrap().send(msgs::UserList::new().into()).await.unwrap(); } ControlPacket::Reject(msg) => { println!("Login rejected: {:?}", msg); } ControlPacket::UserState(msg) => { - println!("Found user {} with id {}", msg.get_name(), msg.get_session()); audio.lock().unwrap().add_client(msg.get_session()); + let mut server = server.lock().unwrap(); + let session = msg.get_session(); + server.parse_user_state(msg); + let user = server.users().get(&session).unwrap(); + println!("User {} connected to {}", + user.name(), + user.channel()); } ControlPacket::UserRemove(msg) => { println!("User {} left", msg.get_session()); audio.lock().unwrap().remove_client(msg.get_session()); } + ControlPacket::ChannelState(msg) => { + server.lock().unwrap().parse_channel_state(msg); + } + ControlPacket::ChannelRemove(msg) => {} + ControlPacket::UserList(msg) => { + println!("User list received"); + println!("{:?}", msg); + } _ => {} } } } pub async fn handle_tcp( + server: Arc>, server_addr: SocketAddr, server_host: String, username: String, @@ -185,7 +212,7 @@ pub async fn handle_tcp( join!( send_pings(Arc::clone(&sink), 10), - listen_tcp(sink, stream, crypt_state_sender, audio), + listen_tcp(server, sink, stream, crypt_state_sender, audio), ); } diff --git a/mumd/src/state.rs b/mumd/src/state.rs new file mode 100644 index 0000000..791d26c --- /dev/null +++ b/mumd/src/state.rs @@ -0,0 +1,201 @@ +use mumble_protocol::control::msgs; +use std::collections::HashMap; +use std::collections::hash_map::Entry; + +pub struct Server { + channels: HashMap, + users: HashMap, + pub welcome_text: Option, +} + +impl Server { + pub fn new() -> Self { + Self { + channels: HashMap::new(), + users: HashMap::new(), + welcome_text: None, + } + } + + pub fn parse_server_sync(&mut self, mut msg: Box) { + if msg.has_welcome_text() { + self.welcome_text = Some(msg.take_welcome_text()); + } + } + + pub fn parse_channel_state(&mut self, msg: Box) { + if !msg.has_channel_id() { + eprintln!("Can't parse channel state without channel id"); + return; + } + match self.channels.entry(msg.get_channel_id()) { + Entry::Vacant(e) => { e.insert(Channel::new(msg)); }, + Entry::Occupied(mut e) => e.get_mut().parse_channel_state(msg), + } + } + + pub fn parse_user_state(&mut self, msg: Box) { + if !msg.has_session() { + eprintln!("Can't parse user state without session"); + return; + } + match self.users.entry(msg.get_session()) { + Entry::Vacant(e) => { e.insert(User::new(msg)); }, + Entry::Occupied(mut e) => e.get_mut().parse_user_state(msg), + } + } + + pub fn channels(&self) -> &HashMap { + &self.channels + } + + pub fn users(&self) -> &HashMap { + &self.users + } +} + + +pub struct Channel { + description: Option, + links: Vec, + max_users: u32, + name: String, + parent: Option, + position: i32, +} + +impl Channel { + pub fn new(mut msg: Box) -> Self { + Self { + description: if msg.has_description() { + Some(msg.take_description()) + } else { + None + }, + links: Vec::new(), + max_users: msg.get_max_users(), + name: msg.take_name(), + parent: if msg.has_parent() { + Some(msg.get_parent()) + } else { + None + }, + position: msg.get_position(), + } + } + + pub fn parse_channel_state(&mut self, mut msg: Box) { + if msg.has_description() { + self.description = Some(msg.take_description()); + } + self.links = msg.take_links(); + if msg.has_max_users() { + self.max_users = msg.get_max_users(); + } + if msg.has_name() { + self.name = msg.take_name(); + } + if msg.has_parent() { + self.parent = Some(msg.get_parent()); + } + if msg.has_position() { + self.position = msg.get_position(); + } + } + + pub fn name(&self) -> &str { + &self.name + } +} + +pub struct User { + channel: u32, + comment: Option, + hash: Option, + name: String, + priority_speaker: bool, + recording: bool, + + suppress: bool, // by me + self_mute: bool, // by self + self_deaf: bool, // by self + mute: bool, // by admin + deaf: bool, // by admin +} + +impl User { + pub fn new(mut msg: Box) -> Self { + Self { + channel: msg.get_channel_id(), + comment: if msg.has_comment() { + Some(msg.take_comment()) + } else { + None + }, + hash: if msg.has_hash() { + Some(msg.take_hash()) + } else { + None + }, + name: msg.take_name(), + priority_speaker: msg.has_priority_speaker() + && msg.get_priority_speaker(), + recording: msg.has_recording() + && msg.get_recording(), + suppress: msg.has_suppress() + && msg.get_suppress(), + self_mute: msg.has_self_mute() + && msg.get_self_mute(), + self_deaf: msg.has_self_deaf() + && msg.get_self_deaf(), + mute: msg.has_mute() + && msg.get_mute(), + deaf: msg.has_deaf() + && msg.get_deaf(), + } + } + + pub fn parse_user_state(&mut self, mut msg: Box) { + if msg.has_channel_id() { + self.channel = msg.get_channel_id(); + } + if msg.has_comment() { + self.comment = Some(msg.take_comment()); + } + if msg.has_hash() { + self.hash = Some(msg.take_hash()); + } + if msg.has_name() { + self.name = msg.take_name(); + } + if msg.has_priority_speaker() { + self.priority_speaker = msg.get_priority_speaker(); + } + if msg.has_recording() { + self.recording = msg.get_recording(); + } + if msg.has_suppress() { + self.suppress = msg.get_suppress(); + } + if msg.has_self_mute() { + self.self_mute = msg.get_self_mute(); + } + if msg.has_self_deaf() { + self.self_deaf = msg.get_self_deaf(); + } + if msg.has_mute() { + self.mute = msg.get_mute(); + } + if msg.has_deaf() { + self.deaf = msg.get_deaf(); + } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn channel(&self) -> u32 { + self.channel + } +} diff --git a/todo.org b/todo.org index d9dbf3c..dcd2739 100644 --- a/todo.org +++ b/todo.org @@ -2,8 +2,6 @@ * Bättre error handling * Split audio input/output -* Fixa att den blir ledsen om man andas fel -Det ser ut att vara klienter med lägre bitrate som orsakar problem. * Ljudvolymen * REPL ** quit (+ graceful exit) @@ -13,7 +11,10 @@ Det ser ut att vara klienter med lägre bitrate som orsakar problem. * Kombinera flera ljudkällor rimligt (utan clipping) * Mindre pub * UDP crypt state resync?? Kommentar från exemplet +Se Mumble.proto: CryptSetup. Både server och klient kan skicka en tom request +för att skaffa en ny crypt. * Refaktorera TCP-paket * Dela upp network.rs i network/tcp.rs, network/udp.rs * Coolare invalid cert-check * Bättre logging +https://crates.io/crates/log -- cgit v1.2.1