aboutsummaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorKunal Mohan <kunalmohan99@gmail.com>2021-05-16 16:42:50 +0530
committerKunal Mohan <kunalmohan99@gmail.com>2021-05-16 21:41:56 +0530
commit2038947a14d32d89da2bdbcaa1381c3015ac9c7a (patch)
tree5a332470e32b380816098594a89d3c3db1f6eb53 /src/server
parenthandle error on termios initialization (#511) (diff)
downloadsl0ppij-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.rs288
-rw-r--r--src/server/route.rs215
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();
- }
- }
- }
-}