diff --git a/src/common/errors.rs b/src/common/errors.rs index 234745ad0..835274481 100644 --- a/src/common/errors.rs +++ b/src/common/errors.rs @@ -146,6 +146,7 @@ pub enum ContextType { Plugin(PluginContext), /// An app-related call. App(AppContext), + /// A server-related call. IPCServer(ServerContext), StdinHandler, AsyncTask, @@ -297,6 +298,7 @@ impl From<&PtyInstruction> for PtyContext { } } +/// Stack call representations corresponding to the different types of [`ServerOsApiInstruction`]s. #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] pub enum OsContext { SetTerminalSizeUsingFd, @@ -372,7 +374,7 @@ impl From<&AppInstruction> for AppContext { } } -/// Stack call representations corresponding to the different types of [`AppInstruction`]s. +/// Stack call representations corresponding to the different types of [`ServerInstruction`]s. #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] pub enum ServerContext { OpenFile, diff --git a/src/common/mod.rs b/src/common/mod.rs index 9554eb78b..ec1f0959d 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -42,6 +42,8 @@ use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value}; use wasmer_wasi::{Pipe, WasiState}; use zellij_tile::data::{EventType, InputMode, ModeInfo}; +pub const IPC_BUFFER_SIZE: u32 = 8192; + #[derive(Serialize, Deserialize, Debug, Clone)] pub enum ServerInstruction { OpenFile(PathBuf), @@ -205,7 +207,7 @@ pub fn start( opts: CliArgs, server_os_input: Box, ) { - let (ipc_thread, server_name) = start_server(server_os_input.clone(), opts.clone()); + let ipc_thread = start_server(server_os_input.clone(), opts.clone()); let take_snapshot = "\u{1b}[?1049h"; os_input.unset_raw_mode(0); @@ -235,9 +237,9 @@ pub fn start( let mut send_app_instructions = SenderWithContext::new(err_ctx, SenderType::SyncSender(send_app_instructions)); - let (client_buffer_path, client_buffer) = SharedRingBuffer::create_temp(8192).unwrap(); - let mut send_server_instructions = - IpcSenderWithContext::new(SharedRingBuffer::open(&server_name).unwrap()); + let (client_buffer_path, client_buffer) = + SharedRingBuffer::create_temp(IPC_BUFFER_SIZE).unwrap(); + let mut send_server_instructions = os_input.get_server_sender().unwrap(); send_server_instructions .send(ServerInstruction::NewClient(client_buffer_path)) .unwrap(); diff --git a/src/common/os_input_output.rs b/src/common/os_input_output.rs index d0c13ccdc..90bd0e491 100644 --- a/src/common/os_input_output.rs +++ b/src/common/os_input_output.rs @@ -1,5 +1,7 @@ +use crate::common::{IpcSenderWithContext, IPC_BUFFER_SIZE}; use crate::panes::PositionAndSize; -use crate::utils::shared::default_palette; +use crate::utils::consts::ZELLIJ_IPC_PIPE; +use ipmpsc::{Receiver as IpcReceiver, Result as IpcResult, SharedRingBuffer}; use nix::fcntl::{fcntl, FcntlArg, OFlag}; use nix::pty::{forkpty, Winsize}; use nix::sys::signal::{kill, Signal}; @@ -8,6 +10,7 @@ use nix::sys::wait::waitpid; use nix::unistd; use nix::unistd::{ForkResult, Pid}; use serde::{Deserialize, Serialize}; +use std::env; use std::io; use std::io::prelude::*; use std::os::unix::io::RawFd; @@ -15,10 +18,6 @@ use std::path::PathBuf; use std::process::{Child, Command}; use std::sync::{Arc, Mutex}; -use signal_hook::{consts::signal::*, iterator::Signals}; - -use std::env; - fn into_raw_mode(pid: RawFd) { let mut tio = termios::tcgetattr(pid).expect("could not get terminal attribute"); termios::cfmakeraw(&mut tio); @@ -158,6 +157,7 @@ fn spawn_terminal(file_to_open: Option, orig_termios: termios::Termios) #[derive(Clone)] pub struct ServerOsInputOutput { orig_termios: Arc>, + server_buffer: SharedRingBuffer, } /// The `ServerOsApi` trait represents an abstract interface to the features of an operating system that @@ -180,6 +180,8 @@ pub trait ServerOsApi: Send + Sync { fn kill(&mut self, pid: RawFd) -> Result<(), nix::Error>; /// Returns a [`Box`] pointer to this [`OsApi`] struct. fn box_clone(&self) -> Box; + fn get_server_receiver(&self) -> IpcReceiver; + fn get_server_sender(&self) -> IpcSenderWithContext; } impl ServerOsApi for ServerOsInputOutput { @@ -207,6 +209,12 @@ impl ServerOsApi for ServerOsInputOutput { waitpid(Pid::from_raw(pid), None).unwrap(); Ok(()) } + fn get_server_receiver(&self) -> IpcReceiver { + IpcReceiver::new(self.server_buffer.clone()) + } + fn get_server_sender(&self) -> IpcSenderWithContext { + IpcSenderWithContext::new(self.server_buffer.clone()) + } } impl Clone for Box { @@ -218,9 +226,14 @@ impl Clone for Box { pub fn get_server_os_input() -> ServerOsInputOutput { let current_termios = termios::tcgetattr(0).unwrap(); let orig_termios = Arc::new(Mutex::new(current_termios)); - ServerOsInputOutput { orig_termios } + let server_buffer = SharedRingBuffer::create(ZELLIJ_IPC_PIPE, IPC_BUFFER_SIZE).unwrap(); + ServerOsInputOutput { + orig_termios, + server_buffer, + } } +/// OS Instructions sent to the Server by clients #[derive(Serialize, Deserialize, Debug, Clone)] pub enum ServerOsApiInstruction { SetTerminalSizeUsingFd(RawFd, u16, u16), @@ -251,6 +264,7 @@ pub trait ClientOsApi: Send + Sync { fn read_from_stdin(&self) -> Vec; /// Returns a [`Box`] pointer to this [`OsApi`] struct. fn box_clone(&self) -> Box; + fn get_server_sender(&self) -> IpcResult; } impl ClientOsApi for ClientOsInputOutput { @@ -280,6 +294,10 @@ impl ClientOsApi for ClientOsInputOutput { let stdout = ::std::io::stdout(); Box::new(stdout) } + fn get_server_sender(&self) -> IpcResult { + let buffer = SharedRingBuffer::open(ZELLIJ_IPC_PIPE)?; + Ok(IpcSenderWithContext::new(buffer)) + } } impl Clone for Box { diff --git a/src/main.rs b/src/main.rs index 5c0049ecc..e6b94064b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -87,8 +87,8 @@ pub fn main() { .send(ServerInstruction::OpenFile(file_to_open)) .unwrap(); } else { - let os_input = get_client_os_input(); let server_os_input = get_server_os_input(); + let os_input = get_client_os_input(); atomic_create_dir(ZELLIJ_TMP_DIR).unwrap(); atomic_create_dir(ZELLIJ_TMP_LOG_DIR).unwrap(); start(Box::new(os_input), opts, Box::new(server_os_input)); diff --git a/src/server/mod.rs b/src/server/mod.rs index b13180619..3c6918eaf 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -8,16 +8,12 @@ use crate::os_input_output::{ServerOsApi, ServerOsApiInstruction}; use crate::panes::PaneId; use crate::pty_bus::{PtyBus, PtyInstruction}; use crate::screen::ScreenInstruction; -use crate::utils::consts::ZELLIJ_IPC_PIPE; -use ipmpsc::{Receiver as IpcReceiver, SharedRingBuffer}; +use ipmpsc::SharedRingBuffer; use std::path::PathBuf; use std::sync::mpsc::channel; use std::thread; -pub fn start_server( - os_input: Box, - opts: CliArgs, -) -> (thread::JoinHandle<()>, String) { +pub fn start_server(os_input: Box, opts: CliArgs) -> thread::JoinHandle<()> { let (send_pty_instructions, receive_pty_instructions): ChannelWithContext = channel(); let mut send_pty_instructions = SenderWithContext::new( @@ -25,14 +21,6 @@ pub fn start_server( SenderType::Sender(send_pty_instructions), ); - #[cfg(not(test))] - let (server_name, server_buffer) = ( - String::from(ZELLIJ_IPC_PIPE), - SharedRingBuffer::create(ZELLIJ_IPC_PIPE, 8192).unwrap(), - ); - #[cfg(test)] - let (server_name, server_buffer) = SharedRingBuffer::create_temp(8192).unwrap(); - let (send_os_instructions, receive_os_instructions): ChannelWithContext< ServerOsApiInstruction, > = channel(); @@ -48,7 +36,7 @@ pub fn start_server( let default_layout = None; let maybe_layout = opts.layout.or(default_layout); - let send_server_instructions = IpcSenderWithContext::new(server_buffer.clone()); + let send_server_instructions = os_input.get_server_sender(); let mut pty_bus = PtyBus::new( receive_pty_instructions, @@ -151,10 +139,10 @@ pub fn start_server( }) .unwrap(); - let server_handle = thread::Builder::new() + thread::Builder::new() .name("ipc_server".to_string()) .spawn({ - let recv_server_instructions = IpcReceiver::new(server_buffer); + let recv_server_instructions = os_input.get_server_receiver(); // Fixme: We cannot use uninitialised sender, therefore this Vec. // For now, We make sure that the first message is `NewClient` so there are no out of bound panics. let mut send_client_instructions: Vec = Vec::with_capacity(1); @@ -228,6 +216,5 @@ pub fn start_server( } } }) - .unwrap(); - (server_handle, server_name) + .unwrap() } diff --git a/src/tests/fakes.rs b/src/tests/fakes.rs index 8621de71f..80cf67b55 100644 --- a/src/tests/fakes.rs +++ b/src/tests/fakes.rs @@ -1,4 +1,5 @@ use crate::panes::PositionAndSize; +use ipmpsc::{Receiver as IpcReceiver, Result as IpcResult, SharedRingBuffer}; use std::collections::{HashMap, VecDeque}; use std::io::Write; use std::os::unix::io::RawFd; @@ -6,6 +7,7 @@ use std::path::PathBuf; use std::sync::{Arc, Condvar, Mutex}; use std::time::{Duration, Instant}; +use crate::common::{IpcSenderWithContext, IPC_BUFFER_SIZE}; use crate::os_input_output::{ClientOsApi, ServerOsApi}; use crate::tests::possible_tty_inputs::{get_possible_tty_inputs, Bytes}; use crate::utils::shared::default_palette; @@ -73,8 +75,8 @@ pub struct FakeInputOutput { win_sizes: Arc>>, possible_tty_inputs: HashMap, last_snapshot_time: Arc>, - should_trigger_sigwinch: Arc<(Mutex, Condvar)>, - sigwinch_event: Option, + started_reading_from_pty: Arc, + server_buffer: SharedRingBuffer, } impl FakeInputOutput { @@ -82,7 +84,9 @@ impl FakeInputOutput { let mut win_sizes = HashMap::new(); let last_snapshot_time = Arc::new(Mutex::new(Instant::now())); let stdout_writer = FakeStdoutWriter::new(last_snapshot_time.clone()); + let (_, server_buffer) = SharedRingBuffer::create_temp(IPC_BUFFER_SIZE).unwrap(); win_sizes.insert(0, winsize); // 0 is the current terminal + FakeInputOutput { read_buffers: Arc::new(Mutex::new(HashMap::new())), stdin_writes: Arc::new(Mutex::new(HashMap::new())), @@ -93,8 +97,8 @@ impl FakeInputOutput { io_events: Arc::new(Mutex::new(vec![])), win_sizes: Arc::new(Mutex::new(win_sizes)), possible_tty_inputs: get_possible_tty_inputs(), - should_trigger_sigwinch: Arc::new((Mutex::new(false), Condvar::new())), - sigwinch_event: None, + started_reading_from_pty: Arc::new(AtomicBool::new(false)), + server_buffer, } } pub fn with_tty_inputs(mut self, tty_inputs: HashMap) -> Self { @@ -162,6 +166,9 @@ impl ClientOsApi for FakeInputOutput { fn get_stdout_writer(&self) -> Box { Box::new(self.stdout_writer.clone()) } + fn get_server_sender(&self) -> IpcResult { + Ok(IpcSenderWithContext::new(self.server_buffer.clone())) + } } impl ServerOsApi for FakeInputOutput { @@ -222,15 +229,11 @@ impl ServerOsApi for FakeInputOutput { self.io_events.lock().unwrap().push(IoEvent::Kill(fd)); Ok(()) } - fn receive_sigwinch(&self, cb: Box) { - if self.sigwinch_event.is_some() { - let (lock, cvar) = &*self.should_trigger_sigwinch; - let mut should_trigger_sigwinch = lock.lock().unwrap(); - while !*should_trigger_sigwinch { - should_trigger_sigwinch = cvar.wait(should_trigger_sigwinch).unwrap(); - } - cb(); - } + fn get_server_receiver(&self) -> IpcReceiver { + IpcReceiver::new(self.server_buffer.clone()) + } + fn get_server_sender(&self) -> IpcSenderWithContext { + IpcSenderWithContext::new(self.server_buffer.clone()) } fn load_palette(&self) -> Palette { default_palette()