diff options
| author | Kunal Mohan <kunalmohan99@gmail.com> | 2021-05-03 17:23:32 +0530 |
|---|---|---|
| committer | Kunal Mohan <kunalmohan99@gmail.com> | 2021-05-04 20:48:17 +0530 |
| commit | ea552d71e4b1d4a72d30f4481079cb0e30b0fc58 (patch) | |
| tree | d557367d1b170e0ce517dc8effd1175783cb6fd1 /src | |
| parent | use better names for senders, receivers and threads (diff) | |
| download | sl0ppij-ea552d71e4b1d4a72d30f4481079cb0e30b0fc58.tar.gz sl0ppij-ea552d71e4b1d4a72d30f4481079cb0e30b0fc58.tar.xz sl0ppij-ea552d71e4b1d4a72d30f4481079cb0e30b0fc58.zip | |
Introduce IpcReceiverWIthContext and move ipc stuff to common/ipc.rs
Fall back to /tmp/zellij-{uid} directory if runtime_dir is not available.
Use serialize_into() to avoid Vec allocation.
And some cleanup
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/ipc.rs | 72 | ||||
| -rw-r--r-- | src/common/mod.rs | 15 | ||||
| -rw-r--r-- | src/common/os_input_output.rs | 94 | ||||
| -rw-r--r-- | src/common/utils/consts.rs | 20 | ||||
| -rw-r--r-- | src/server/mod.rs | 2 |
5 files changed, 121 insertions, 82 deletions
diff --git a/src/common/ipc.rs b/src/common/ipc.rs index 68aa676b..190680dc 100644 --- a/src/common/ipc.rs +++ b/src/common/ipc.rs @@ -1,7 +1,13 @@ //! IPC stuff for starting to split things into a client and server model. +use crate::common::errors::{get_current_ctx, ErrorContext}; +use interprocess::local_socket::LocalSocketStream; +use nix::unistd::dup; use serde::{Deserialize, Serialize}; use std::collections::HashSet; +use std::io::{self, Write}; +use std::marker::PhantomData; +use std::os::unix::io::{AsRawFd, FromRawFd}; type SessionId = u64; @@ -45,3 +51,69 @@ pub enum _ServerToClientMsg { // A list of sessions SessionList(HashSet<Session>), } + +/// Sends messages on a stream socket, along with an [`ErrorContext`]. +pub struct IpcSenderWithContext<T: Serialize> { + sender: io::BufWriter<LocalSocketStream>, + _phantom: PhantomData<T>, +} + +impl<T: Serialize> IpcSenderWithContext<T> { + /// Returns a sender to the given [LocalSocketStream](interprocess::local_socket::LocalSocketStream). + pub fn new(sender: LocalSocketStream) -> Self { + Self { + sender: io::BufWriter::new(sender), + _phantom: PhantomData, + } + } + + /// Sends an event, along with the current [`ErrorContext`], on this [`IpcSenderWithContext`]'s socket. + pub fn send(&mut self, msg: T) { + let err_ctx = get_current_ctx(); + bincode::serialize_into(&mut self.sender, &(msg, err_ctx)).unwrap(); + self.sender.flush().unwrap(); + } + + /// Returns an [`IpcReceiverWithContext`] with the same socket as this sender. + pub fn get_receiver<F>(&self) -> IpcReceiverWithContext<F> + where + F: for<'de> Deserialize<'de> + Serialize, + { + let sock_fd = self.sender.get_ref().as_raw_fd(); + let dup_sock = dup(sock_fd).unwrap(); + let socket = unsafe { LocalSocketStream::from_raw_fd(dup_sock) }; + IpcReceiverWithContext::new(socket) + } +} + +/// Receives messages on a stream socket, along with an [`ErrorContext`]. +pub struct IpcReceiverWithContext<T> { + receiver: io::BufReader<LocalSocketStream>, + _phantom: PhantomData<T>, +} + +impl<T> IpcReceiverWithContext<T> +where + T: for<'de> Deserialize<'de> + Serialize, +{ + /// Returns a receiver to the given [LocalSocketStream](interprocess::local_socket::LocalSocketStream). + pub fn new(receiver: LocalSocketStream) -> Self { + Self { + receiver: io::BufReader::new(receiver), + _phantom: PhantomData, + } + } + + /// Receives an event, along with the current [`ErrorContext`], on this [`IpcReceiverWithContext`]'s socket. + pub fn recv(&mut self) -> (T, ErrorContext) { + bincode::deserialize_from(&mut self.receiver).unwrap() + } + + /// Returns an [`IpcSenderWithContext`] with the same socket as this receiver. + pub fn get_sender<F: Serialize>(&self) -> IpcSenderWithContext<F> { + let sock_fd = self.receiver.get_ref().as_raw_fd(); + let dup_sock = dup(sock_fd).unwrap(); + let socket = unsafe { LocalSocketStream::from_raw_fd(dup_sock) }; + IpcSenderWithContext::new(socket) + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs index bf4c3ae6..6061f1a6 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -12,11 +12,8 @@ pub mod wasm_vm; use crate::panes::PaneId; use crate::server::ServerInstruction; use async_std::task_local; -use directories_next::ProjectDirs; use errors::{get_current_ctx, ErrorContext}; -use lazy_static::lazy_static; use std::cell::RefCell; -use std::path::PathBuf; use std::sync::mpsc; /// An [MPSC](mpsc) asynchronous channel with added error context. @@ -76,15 +73,3 @@ task_local! { /// stack in the form of an [`ErrorContext`]. static ASYNCOPENCALLS: RefCell<ErrorContext> = RefCell::default() } - -lazy_static! { - pub static ref ZELLIJ_IPC_PIPE: PathBuf = { - let project_dir = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap(); - let ipc_dir = project_dir - .runtime_dir() - .unwrap_or_else(|| project_dir.cache_dir()); - std::fs::create_dir_all(ipc_dir).unwrap(); - let session_name = names::Generator::default().next().unwrap(); - ipc_dir.join(session_name) - }; -} diff --git a/src/common/os_input_output.rs b/src/common/os_input_output.rs index 9a124011..a339b08d 100644 --- a/src/common/os_input_output.rs +++ b/src/common/os_input_output.rs @@ -5,20 +5,21 @@ use nix::sys::signal::{kill, Signal}; use nix::sys::termios; use nix::sys::wait::waitpid; use nix::unistd::{self, ForkResult, Pid}; -use serde::Serialize; use signal_hook::{consts::signal::*, iterator::Signals}; use std::env; use std::io; use std::io::prelude::*; -use std::marker::PhantomData; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use std::os::unix::io::RawFd; use std::path::PathBuf; use std::process::{Child, Command}; use std::sync::{Arc, Mutex}; use crate::client::ClientInstruction; -use crate::common::ZELLIJ_IPC_PIPE; -use crate::errors::{get_current_ctx, ErrorContext}; +use crate::common::{ + ipc::{IpcReceiverWithContext, IpcSenderWithContext}, + utils::consts::ZELLIJ_IPC_PIPE, +}; +use crate::errors::ErrorContext; use crate::panes::PositionAndSize; use crate::server::ServerInstruction; @@ -158,35 +159,10 @@ fn spawn_terminal(file_to_open: Option<PathBuf>, orig_termios: termios::Termios) (pid_primary, pid_secondary) } -/// Sends messages on an [ipmpsc](ipmpsc) channel, along with an [`ErrorContext`]. -struct IpcSenderWithContext<T: Serialize> { - sender: io::BufWriter<LocalSocketStream>, - _phantom: PhantomData<T>, -} - -impl<T: Serialize> IpcSenderWithContext<T> { - /// Returns a sender to the given [SharedRingBuffer](ipmpsc::SharedRingBuffer). - fn new(sender: LocalSocketStream) -> Self { - Self { - sender: io::BufWriter::new(sender), - _phantom: PhantomData, - } - } - - /// Sends an event, along with the current [`ErrorContext`], on this - /// [`IpcSenderWithContext`]'s channel. - fn send(&mut self, msg: T) -> Result<(), std::io::Error> { - let err_ctx = get_current_ctx(); - self.sender - .write_all(&bincode::serialize(&(msg, err_ctx)).unwrap())?; - self.sender.flush() - } -} - #[derive(Clone)] pub struct ServerOsInputOutput { orig_termios: Arc<Mutex<termios::Termios>>, - receive_instructions_from_client: Option<Arc<Mutex<io::BufReader<LocalSocketStream>>>>, + receive_instructions_from_client: Option<Arc<Mutex<IpcReceiverWithContext<ServerInstruction>>>>, send_instructions_to_client: Arc<Mutex<Option<IpcSenderWithContext<ClientInstruction>>>>, } @@ -252,15 +228,12 @@ impl ServerOsApi for ServerOsInputOutput { Ok(()) } fn recv_from_client(&self) -> (ServerInstruction, ErrorContext) { - bincode::deserialize_from( - &mut *self - .receive_instructions_from_client - .as_ref() - .unwrap() - .lock() - .unwrap(), - ) - .unwrap() + self.receive_instructions_from_client + .as_ref() + .unwrap() + .lock() + .unwrap() + .recv() } fn send_to_client(&self, msg: ClientInstruction) { self.send_instructions_to_client @@ -268,27 +241,22 @@ impl ServerOsApi for ServerOsInputOutput { .unwrap() .as_mut() .unwrap() - .send(msg) - .unwrap(); + .send(msg); } fn add_client_sender(&mut self) { assert!(self.send_instructions_to_client.lock().unwrap().is_none()); - let sock_fd = self + let sender = self .receive_instructions_from_client .as_ref() .unwrap() .lock() .unwrap() - .get_ref() - .as_raw_fd(); - let dup_fd = unistd::dup(sock_fd).unwrap(); - let dup_sock = unsafe { LocalSocketStream::from_raw_fd(dup_fd) }; - *self.send_instructions_to_client.lock().unwrap() = - Some(IpcSenderWithContext::new(dup_sock)); + .get_sender(); + *self.send_instructions_to_client.lock().unwrap() = Some(sender); } fn update_receiver(&mut self, stream: LocalSocketStream) { self.receive_instructions_from_client = - Some(Arc::new(Mutex::new(io::BufReader::new(stream)))); + Some(Arc::new(Mutex::new(IpcReceiverWithContext::new(stream)))); } } @@ -312,7 +280,7 @@ pub fn get_server_os_input() -> ServerOsInputOutput { pub struct ClientOsInputOutput { orig_termios: Arc<Mutex<termios::Termios>>, send_instructions_to_server: Arc<Mutex<Option<IpcSenderWithContext<ServerInstruction>>>>, - receive_instructions_from_server: Arc<Mutex<Option<io::BufReader<LocalSocketStream>>>>, + receive_instructions_from_server: Arc<Mutex<Option<IpcReceiverWithContext<ClientInstruction>>>>, } /// The `ClientOsApi` trait represents an abstract interface to the features of an operating system that @@ -375,19 +343,15 @@ impl ClientOsApi for ClientOsInputOutput { .unwrap() .as_mut() .unwrap() - .send(msg) - .unwrap(); + .send(msg); } fn recv_from_server(&self) -> (ClientInstruction, ErrorContext) { - bincode::deserialize_from( - &mut self - .receive_instructions_from_server - .lock() - .unwrap() - .as_mut() - .unwrap(), - ) - .unwrap() + self.receive_instructions_from_server + .lock() + .unwrap() + .as_mut() + .unwrap() + .recv() } fn receive_sigwinch(&self, cb: Box<dyn Fn()>) { let mut signals = Signals::new(&[SIGWINCH, SIGTERM, SIGINT, SIGQUIT]).unwrap(); @@ -411,12 +375,10 @@ impl ClientOsApi for ClientOsInputOutput { LocalSocketStream::connect(ZELLIJ_IPC_PIPE.clone()).unwrap() } }; - let sock_fd = socket.as_raw_fd(); - let dup_fd = unistd::dup(sock_fd).unwrap(); - let receiver = unsafe { LocalSocketStream::from_raw_fd(dup_fd) }; let sender = IpcSenderWithContext::new(socket); + let receiver = sender.get_receiver(); *self.send_instructions_to_server.lock().unwrap() = Some(sender); - *self.receive_instructions_from_server.lock().unwrap() = Some(io::BufReader::new(receiver)); + *self.receive_instructions_from_server.lock().unwrap() = Some(receiver); } } diff --git a/src/common/utils/consts.rs b/src/common/utils/consts.rs index f031dd38..c21e3029 100644 --- a/src/common/utils/consts.rs +++ b/src/common/utils/consts.rs @@ -1,5 +1,25 @@ //! Zellij program-wide constants. +use directories_next::ProjectDirs; +use lazy_static::lazy_static; +use nix::unistd::Uid; +use std::path::PathBuf; + pub const ZELLIJ_TMP_DIR: &str = "/tmp/zellij"; pub const ZELLIJ_TMP_LOG_DIR: &str = "/tmp/zellij/zellij-log"; pub const ZELLIJ_TMP_LOG_FILE: &str = "/tmp/zellij/zellij-log/log.txt"; + +lazy_static! { + static ref UID: Uid = Uid::current(); + pub static ref SESSION_NAME: String = names::Generator::default().next().unwrap(); + pub static ref ZELLIJ_IPC_PIPE: PathBuf = { + let project_dir = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap(); + let mut ipc_dir = project_dir + .runtime_dir() + .map(|p| p.to_owned()) + .unwrap_or_else(|| PathBuf::from("/tmp/zellij-".to_string() + &format!("{}", *UID))); + std::fs::create_dir_all(&ipc_dir).unwrap(); + ipc_dir.push(&*SESSION_NAME); + ipc_dir + }; +} diff --git a/src/server/mod.rs b/src/server/mod.rs index c1f93d5b..25a95222 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -16,7 +16,6 @@ use zellij_tile::data::{Event, EventType, ModeInfo}; use crate::cli::CliArgs; use crate::client::ClientInstruction; -use crate::common::ZELLIJ_IPC_PIPE; use crate::common::{ errors::{ContextType, PluginContext, PtyContext, ScreenContext, ServerContext}, input::actions::{Action, Direction}, @@ -24,6 +23,7 @@ use crate::common::{ os_input_output::ServerOsApi, pty_bus::{PtyBus, PtyInstruction}, screen::{Screen, ScreenInstruction}, + utils::consts::ZELLIJ_IPC_PIPE, wasm_vm::{wasi_stdout, wasi_write_string, zellij_imports, PluginEnv, PluginInstruction}, ChannelWithContext, SenderType, SenderWithContext, }; |
