diff options
| author | Kunal Mohan <kunalmohan99@gmail.com> | 2021-05-16 16:42:50 +0530 |
|---|---|---|
| committer | Kunal Mohan <kunalmohan99@gmail.com> | 2021-05-16 21:41:56 +0530 |
| commit | 2038947a14d32d89da2bdbcaa1381c3015ac9c7a (patch) | |
| tree | 5a332470e32b380816098594a89d3c3db1f6eb53 /src/server | |
| parent | handle error on termios initialization (#511) (diff) | |
| download | sl0ppij-2038947a14d32d89da2bdbcaa1381c3015ac9c7a.tar.gz sl0ppij-2038947a14d32d89da2bdbcaa1381c3015ac9c7a.tar.xz sl0ppij-2038947a14d32d89da2bdbcaa1381c3015ac9c7a.zip | |
Big refactor: separate crates for client, server and utilities
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/mod.rs | 288 | ||||
| -rw-r--r-- | src/server/route.rs | 215 |
2 files changed, 0 insertions, 503 deletions
diff --git a/src/server/mod.rs b/src/server/mod.rs deleted file mode 100644 index 4c6fb757..00000000 --- a/src/server/mod.rs +++ /dev/null @@ -1,288 +0,0 @@ -pub mod route; - -use std::sync::{Arc, RwLock}; -use std::thread; -use std::{path::PathBuf, sync::mpsc}; -use wasmer::Store; -use zellij_tile::data::PluginCapabilities; - -use crate::cli::CliArgs; -use crate::common::thread_bus::{Bus, ThreadSenders}; -use crate::common::{ - errors::ContextType, - input::options::Options, - ipc::{ClientToServerMsg, ServerToClientMsg}, - os_input_output::ServerOsApi, - pty::{pty_thread_main, Pty, PtyInstruction}, - screen::{screen_thread_main, ScreenInstruction}, - setup::{get_default_data_dir, install::populate_data_dir}, - thread_bus::{ChannelWithContext, SenderType, SenderWithContext, SyncChannelWithContext}, - wasm_vm::{wasm_thread_main, PluginInstruction}, -}; -use crate::layout::Layout; -use crate::panes::PositionAndSize; -use route::route_thread_main; - -/// Instructions related to server-side application including the -/// ones sent by client to server -#[derive(Debug, Clone)] -pub enum ServerInstruction { - NewClient(PositionAndSize, CliArgs, Options), - Render(Option<String>), - UnblockInputThread, - ClientExit, - Error(String), -} - -impl From<ClientToServerMsg> for ServerInstruction { - fn from(instruction: ClientToServerMsg) -> Self { - match instruction { - ClientToServerMsg::ClientExit => ServerInstruction::ClientExit, - ClientToServerMsg::NewClient(pos, opts, options) => { - ServerInstruction::NewClient(pos, opts, options) - } - _ => unreachable!(), - } - } -} - -pub struct SessionMetaData { - pub senders: ThreadSenders, - pub capabilities: PluginCapabilities, - screen_thread: Option<thread::JoinHandle<()>>, - pty_thread: Option<thread::JoinHandle<()>>, - wasm_thread: Option<thread::JoinHandle<()>>, -} - -impl Drop for SessionMetaData { - fn drop(&mut self) { - let _ = self.senders.send_to_pty(PtyInstruction::Exit); - let _ = self.senders.send_to_screen(ScreenInstruction::Exit); - let _ = self.senders.send_to_plugin(PluginInstruction::Exit); - let _ = self.screen_thread.take().unwrap().join(); - let _ = self.pty_thread.take().unwrap().join(); - let _ = self.wasm_thread.take().unwrap().join(); - } -} - -pub fn start_server(os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) { - #[cfg(not(test))] - daemonize::Daemonize::new() - .working_directory(std::env::var("HOME").unwrap()) - .umask(0o077) - .start() - .expect("could not daemonize the server process"); - - std::env::set_var(&"ZELLIJ", "0"); - - let (to_server, server_receiver): SyncChannelWithContext<ServerInstruction> = - mpsc::sync_channel(50); - let to_server = SenderWithContext::new(SenderType::SyncSender(to_server)); - let sessions: Arc<RwLock<Option<SessionMetaData>>> = Arc::new(RwLock::new(None)); - - #[cfg(not(test))] - std::panic::set_hook({ - use crate::errors::handle_panic; - let to_server = to_server.clone(); - Box::new(move |info| { - handle_panic(info, &to_server); - }) - }); - - #[cfg(test)] - thread::Builder::new() - .name("server_router".to_string()) - .spawn({ - let sessions = sessions.clone(); - let os_input = os_input.clone(); - let to_server = to_server.clone(); - - move || route_thread_main(sessions, os_input, to_server) - }) - .unwrap(); - #[cfg(not(test))] - let _ = thread::Builder::new() - .name("server_listener".to_string()) - .spawn({ - use crate::common::os_input_output::set_permissions; - use interprocess::local_socket::LocalSocketListener; - - let os_input = os_input.clone(); - let sessions = sessions.clone(); - let to_server = to_server.clone(); - let socket_path = socket_path.clone(); - move || { - drop(std::fs::remove_file(&socket_path)); - let listener = LocalSocketListener::bind(&*socket_path).unwrap(); - set_permissions(&socket_path).unwrap(); - for stream in listener.incoming() { - match stream { - Ok(stream) => { - let mut os_input = os_input.clone(); - os_input.update_receiver(stream); - let sessions = sessions.clone(); - let to_server = to_server.clone(); - thread::Builder::new() - .name("server_router".to_string()) - .spawn({ - let sessions = sessions.clone(); - let os_input = os_input.clone(); - let to_server = to_server.clone(); - - move || route_thread_main(sessions, os_input, to_server) - }) - .unwrap(); - } - Err(err) => { - panic!("err {:?}", err); - } - } - } - } - }); - - loop { - let (instruction, mut err_ctx) = server_receiver.recv().unwrap(); - err_ctx.add_call(ContextType::IPCServer((&instruction).into())); - match instruction { - ServerInstruction::NewClient(full_screen_ws, opts, config_options) => { - let session_data = init_session( - os_input.clone(), - opts, - config_options, - to_server.clone(), - full_screen_ws, - ); - *sessions.write().unwrap() = Some(session_data); - sessions - .read() - .unwrap() - .as_ref() - .unwrap() - .senders - .send_to_pty(PtyInstruction::NewTab) - .unwrap(); - } - ServerInstruction::UnblockInputThread => { - os_input.send_to_client(ServerToClientMsg::UnblockInputThread); - } - ServerInstruction::ClientExit => { - *sessions.write().unwrap() = None; - os_input.send_to_client(ServerToClientMsg::Exit); - break; - } - ServerInstruction::Render(output) => { - os_input.send_to_client(ServerToClientMsg::Render(output)) - } - ServerInstruction::Error(backtrace) => { - os_input.send_to_client(ServerToClientMsg::ServerError(backtrace)); - break; - } - } - } - #[cfg(not(test))] - drop(std::fs::remove_file(&socket_path)); -} - -fn init_session( - os_input: Box<dyn ServerOsApi>, - opts: CliArgs, - config_options: Options, - to_server: SenderWithContext<ServerInstruction>, - full_screen_ws: PositionAndSize, -) -> SessionMetaData { - let (to_screen, screen_receiver): ChannelWithContext<ScreenInstruction> = mpsc::channel(); - let to_screen = SenderWithContext::new(SenderType::Sender(to_screen)); - - let (to_plugin, plugin_receiver): ChannelWithContext<PluginInstruction> = mpsc::channel(); - let to_plugin = SenderWithContext::new(SenderType::Sender(to_plugin)); - let (to_pty, pty_receiver): ChannelWithContext<PtyInstruction> = mpsc::channel(); - let to_pty = SenderWithContext::new(SenderType::Sender(to_pty)); - - // Determine and initialize the data directory - let data_dir = opts.data_dir.unwrap_or_else(get_default_data_dir); - - #[cfg(not(disable_automatic_asset_installation))] - populate_data_dir(&data_dir); - - let capabilities = PluginCapabilities { - arrow_fonts: config_options.simplified_ui, - }; - - // Don't use default layouts in tests, but do everywhere else - #[cfg(not(test))] - let default_layout = Some(PathBuf::from("default")); - #[cfg(test)] - let default_layout = None; - let maybe_layout = opts - .layout - .map(|p| Layout::new(&p, &data_dir)) - .or_else(|| default_layout.map(|p| Layout::from_defaults(&p, &data_dir))); - - let pty_thread = thread::Builder::new() - .name("pty".to_string()) - .spawn({ - let pty = Pty::new( - Bus::new( - pty_receiver, - Some(&to_screen), - None, - Some(&to_plugin), - Some(&to_server), - Some(os_input.clone()), - ), - opts.debug, - ); - - move || pty_thread_main(pty, maybe_layout) - }) - .unwrap(); - - let screen_thread = thread::Builder::new() - .name("screen".to_string()) - .spawn({ - let screen_bus = Bus::new( - screen_receiver, - None, - Some(&to_pty), - Some(&to_plugin), - Some(&to_server), - Some(os_input.clone()), - ); - let max_panes = opts.max_panes; - - move || { - screen_thread_main(screen_bus, max_panes, full_screen_ws, config_options); - } - }) - .unwrap(); - - let wasm_thread = thread::Builder::new() - .name("wasm".to_string()) - .spawn({ - let plugin_bus = Bus::new( - plugin_receiver, - Some(&to_screen), - Some(&to_pty), - None, - None, - None, - ); - let store = Store::default(); - - move || wasm_thread_main(plugin_bus, store, data_dir) - }) - .unwrap(); - SessionMetaData { - senders: ThreadSenders { - to_screen: Some(to_screen), - to_pty: Some(to_pty), - to_plugin: Some(to_plugin), - to_server: None, - }, - capabilities, - screen_thread: Some(screen_thread), - pty_thread: Some(pty_thread), - wasm_thread: Some(wasm_thread), - } -} diff --git a/src/server/route.rs b/src/server/route.rs deleted file mode 100644 index c435a0e6..00000000 --- a/src/server/route.rs +++ /dev/null @@ -1,215 +0,0 @@ -use std::sync::{Arc, RwLock}; - -use zellij_tile::data::Event; - -use crate::common::input::actions::{Action, Direction}; -use crate::common::input::handler::get_mode_info; -use crate::common::ipc::ClientToServerMsg; -use crate::common::os_input_output::ServerOsApi; -use crate::common::pty::PtyInstruction; -use crate::common::screen::ScreenInstruction; -use crate::common::thread_bus::SenderWithContext; -use crate::common::wasm_vm::PluginInstruction; -use crate::server::{ServerInstruction, SessionMetaData}; - -fn route_action(action: Action, session: &SessionMetaData, os_input: &dyn ServerOsApi) { - match action { - Action::Write(val) => { - session - .senders - .send_to_screen(ScreenInstruction::ClearScroll) - .unwrap(); - session - .senders - .send_to_screen(ScreenInstruction::WriteCharacter(val)) - .unwrap(); - } - Action::SwitchToMode(mode) => { - let palette = os_input.load_palette(); - session - .senders - .send_to_plugin(PluginInstruction::Update( - None, - Event::ModeUpdate(get_mode_info(mode, palette, session.capabilities)), - )) - .unwrap(); - session - .senders - .send_to_screen(ScreenInstruction::ChangeMode(get_mode_info( - mode, - palette, - session.capabilities, - ))) - .unwrap(); - session - .senders - .send_to_screen(ScreenInstruction::Render) - .unwrap(); - } - Action::Resize(direction) => { - let screen_instr = match direction { - Direction::Left => ScreenInstruction::ResizeLeft, - Direction::Right => ScreenInstruction::ResizeRight, - Direction::Up => ScreenInstruction::ResizeUp, - Direction::Down => ScreenInstruction::ResizeDown, - }; - session.senders.send_to_screen(screen_instr).unwrap(); - } - Action::SwitchFocus => { - session - .senders - .send_to_screen(ScreenInstruction::SwitchFocus) - .unwrap(); - } - Action::FocusNextPane => { - session - .senders - .send_to_screen(ScreenInstruction::FocusNextPane) - .unwrap(); - } - Action::FocusPreviousPane => { - session - .senders - .send_to_screen(ScreenInstruction::FocusPreviousPane) - .unwrap(); - } - Action::MoveFocus(direction) => { - let screen_instr = match direction { - Direction::Left => ScreenInstruction::MoveFocusLeft, - Direction::Right => ScreenInstruction::MoveFocusRight, - Direction::Up => ScreenInstruction::MoveFocusUp, - Direction::Down => ScreenInstruction::MoveFocusDown, - }; - session.senders.send_to_screen(screen_instr).unwrap(); - } - Action::MoveFocusOrTab(direction) => { - let screen_instr = match direction { - Direction::Left => ScreenInstruction::MoveFocusLeftOrPreviousTab, - Direction::Right => ScreenInstruction::MoveFocusRightOrNextTab, - _ => unreachable!(), - }; - session.senders.send_to_screen(screen_instr).unwrap(); - } - Action::ScrollUp => { - session - .senders - .send_to_screen(ScreenInstruction::ScrollUp) - .unwrap(); - } - Action::ScrollDown => { - session - .senders - .send_to_screen(ScreenInstruction::ScrollDown) - .unwrap(); - } - Action::PageScrollUp => { - session - .senders - .send_to_screen(ScreenInstruction::PageScrollUp) - .unwrap(); - } - Action::PageScrollDown => { - session - .senders - .send_to_screen(ScreenInstruction::PageScrollDown) - .unwrap(); - } - Action::ToggleFocusFullscreen => { - session - .senders - .send_to_screen(ScreenInstruction::ToggleActiveTerminalFullscreen) - .unwrap(); - } - Action::NewPane(direction) => { - let pty_instr = match direction { - Some(Direction::Left) => PtyInstruction::SpawnTerminalVertically(None), - Some(Direction::Right) => PtyInstruction::SpawnTerminalVertically(None), - Some(Direction::Up) => PtyInstruction::SpawnTerminalHorizontally(None), - Some(Direction::Down) => PtyInstruction::SpawnTerminalHorizontally(None), - // No direction specified - try to put it in the biggest available spot - None => PtyInstruction::SpawnTerminal(None), - }; - session.senders.send_to_pty(pty_instr).unwrap(); - } - Action::CloseFocus => { - session - .senders - .send_to_screen(ScreenInstruction::CloseFocusedPane) - .unwrap(); - } - Action::NewTab => { - session.senders.send_to_pty(PtyInstruction::NewTab).unwrap(); - } - Action::GoToNextTab => { - session - .senders - .send_to_screen(ScreenInstruction::SwitchTabNext) - .unwrap(); - } - Action::GoToPreviousTab => { - session - .senders - .send_to_screen(ScreenInstruction::SwitchTabPrev) - .unwrap(); - } - Action::ToggleActiveSyncTab => { - session - .senders - .send_to_screen(ScreenInstruction::ToggleActiveSyncTab) - .unwrap(); - } - Action::CloseTab => { - session - .senders - .send_to_screen(ScreenInstruction::CloseTab) - .unwrap(); - } - Action::GoToTab(i) => { - session - .senders - .send_to_screen(ScreenInstruction::GoToTab(i)) - .unwrap(); - } - Action::TabNameInput(c) => { - session - .senders - .send_to_screen(ScreenInstruction::UpdateTabName(c)) - .unwrap(); - } - Action::NoOp => {} - Action::Quit => panic!("Received unexpected action"), - } -} - -pub fn route_thread_main( - sessions: Arc<RwLock<Option<SessionMetaData>>>, - mut os_input: Box<dyn ServerOsApi>, - to_server: SenderWithContext<ServerInstruction>, -) { - loop { - let (instruction, err_ctx) = os_input.recv_from_client(); - err_ctx.update_thread_ctx(); - let rlocked_sessions = sessions.read().unwrap(); - match instruction { - ClientToServerMsg::ClientExit => { - to_server.send(instruction.into()).unwrap(); - break; - } - ClientToServerMsg::Action(action) => { - route_action(action, rlocked_sessions.as_ref().unwrap(), &*os_input); - } - ClientToServerMsg::TerminalResize(new_size) => { - rlocked_sessions - .as_ref() - .unwrap() - .senders - .send_to_screen(ScreenInstruction::TerminalResize(new_size)) - .unwrap(); - } - ClientToServerMsg::NewClient(..) => { - os_input.add_client_sender(); - to_server.send(instruction.into()).unwrap(); - } - } - } -} |
