mirror of
https://github.com/zellij-org/zellij.git
synced 2024-12-18 06:32:09 +03:00
Hide server-side Ipc channels creation behind OsApis and some documentation fixes
This commit is contained in:
parent
3ef2715827
commit
bc2345c413
@ -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,
|
||||
|
@ -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<dyn ServerOsApi>,
|
||||
) {
|
||||
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();
|
||||
|
@ -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<PathBuf>, orig_termios: termios::Termios)
|
||||
#[derive(Clone)]
|
||||
pub struct ServerOsInputOutput {
|
||||
orig_termios: Arc<Mutex<termios::Termios>>,
|
||||
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<dyn ServerOsApi>;
|
||||
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<dyn ServerOsApi> {
|
||||
@ -218,9 +226,14 @@ impl Clone for Box<dyn ServerOsApi> {
|
||||
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<u8>;
|
||||
/// Returns a [`Box`] pointer to this [`OsApi`] struct.
|
||||
fn box_clone(&self) -> Box<dyn ClientOsApi>;
|
||||
fn get_server_sender(&self) -> IpcResult<IpcSenderWithContext>;
|
||||
}
|
||||
|
||||
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<IpcSenderWithContext> {
|
||||
let buffer = SharedRingBuffer::open(ZELLIJ_IPC_PIPE)?;
|
||||
Ok(IpcSenderWithContext::new(buffer))
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn ClientOsApi> {
|
||||
|
@ -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));
|
||||
|
@ -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<dyn ServerOsApi>,
|
||||
opts: CliArgs,
|
||||
) -> (thread::JoinHandle<()>, String) {
|
||||
pub fn start_server(os_input: Box<dyn ServerOsApi>, opts: CliArgs) -> thread::JoinHandle<()> {
|
||||
let (send_pty_instructions, receive_pty_instructions): ChannelWithContext<PtyInstruction> =
|
||||
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<IpcSenderWithContext> = Vec::with_capacity(1);
|
||||
@ -228,6 +216,5 @@ pub fn start_server(
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
(server_handle, server_name)
|
||||
.unwrap()
|
||||
}
|
||||
|
@ -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<Mutex<HashMap<RawFd, PositionAndSize>>>,
|
||||
possible_tty_inputs: HashMap<u16, Bytes>,
|
||||
last_snapshot_time: Arc<Mutex<Instant>>,
|
||||
should_trigger_sigwinch: Arc<(Mutex<bool>, Condvar)>,
|
||||
sigwinch_event: Option<PositionAndSize>,
|
||||
started_reading_from_pty: Arc<AtomicBool>,
|
||||
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<u16, Bytes>) -> Self {
|
||||
@ -162,6 +166,9 @@ impl ClientOsApi for FakeInputOutput {
|
||||
fn get_stdout_writer(&self) -> Box<dyn Write> {
|
||||
Box::new(self.stdout_writer.clone())
|
||||
}
|
||||
fn get_server_sender(&self) -> IpcResult<IpcSenderWithContext> {
|
||||
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<dyn Fn()>) {
|
||||
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()
|
||||
|
Loading…
Reference in New Issue
Block a user