mod audio; mod command; mod network; mod state; use crate::network::ConnectionInfo; use crate::state::State; use futures::join; use ipc_channel::ipc::{IpcSender, IpcOneShotServer}; use log::*; use mumble_protocol::control::ControlPacket; use mumble_protocol::crypt::ClientCryptState; use mumble_protocol::voice::Serverbound; use mumlib::command::{Command, CommandResponse}; use mumlib::setup_logger; use std::fs; use std::sync::{Arc, Mutex}; use tokio::sync::{mpsc, watch}; use tokio::task::spawn_blocking; #[tokio::main] async fn main() { setup_logger(); // 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::(1); // crypt state should always be consumed before sending a new one let (packet_sender, packet_receiver) = mpsc::unbounded_channel::>(); let (command_sender, command_receiver) = mpsc::unbounded_channel::<(Command, IpcSender, ()>>)>(); let (connection_info_sender, connection_info_receiver) = watch::channel::>(None); let state = State::new( packet_sender, connection_info_sender, ); let state = Arc::new(Mutex::new(state)); // Run it let (_, _, _, e) = join!( network::tcp::handle( Arc::clone(&state), connection_info_receiver.clone(), crypt_state_sender, packet_receiver, ), network::udp::handle( Arc::clone(&state), connection_info_receiver.clone(), crypt_state_receiver, ), command::handle( state, command_receiver, ), spawn_blocking(move || { receive_oneshot_commands(command_sender); }), ); e.unwrap(); } fn receive_oneshot_commands( command_sender: mpsc::UnboundedSender<(Command, IpcSender, ()>>)>, ) { loop { // create listener let (server, server_name): (IpcOneShotServer<(Command, IpcSender, ()>>)>, String) = IpcOneShotServer::new().unwrap(); fs::write("/var/tmp/mumd-oneshot", &server_name).unwrap(); debug!("Listening for command at {}...", server_name); // receive command and response channel let (_, conn): (_, (Command, IpcSender, ()>>)) = server.accept().unwrap(); debug!("Sending command {:?} to command handler", conn.0); command_sender.send(conn).unwrap(); } }