Use ClientToServerMsg and ServerToClientMsg for IPC
This commit is contained in:
parent
f2c43ac577
commit
c5675e965b
11 changed files with 117 additions and 99 deletions
|
|
@ -4,7 +4,6 @@ pub mod pane_resizer;
|
||||||
pub mod panes;
|
pub mod panes;
|
||||||
pub mod tab;
|
pub mod tab;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::env::current_exe;
|
use std::env::current_exe;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
@ -15,18 +14,17 @@ use std::thread;
|
||||||
use crate::cli::CliArgs;
|
use crate::cli::CliArgs;
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
command_is_executing::CommandIsExecuting,
|
command_is_executing::CommandIsExecuting,
|
||||||
errors::{ClientContext, ContextType},
|
errors::ContextType,
|
||||||
input::config::Config,
|
input::config::Config,
|
||||||
input::handler::input_loop,
|
input::handler::input_loop,
|
||||||
input::options::Options,
|
ipc::{ClientToServerMsg, ServerToClientMsg},
|
||||||
os_input_output::ClientOsApi,
|
os_input_output::ClientOsApi,
|
||||||
thread_bus::{SenderType, SenderWithContext, SyncChannelWithContext},
|
thread_bus::{SenderType, SenderWithContext, SyncChannelWithContext},
|
||||||
utils::consts::ZELLIJ_IPC_PIPE,
|
utils::consts::ZELLIJ_IPC_PIPE,
|
||||||
};
|
};
|
||||||
use crate::server::ServerInstruction;
|
|
||||||
|
|
||||||
/// Instructions related to the client-side application and sent from server to client
|
/// Instructions related to the client-side application and sent from server to client
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ClientInstruction {
|
pub enum ClientInstruction {
|
||||||
Error(String),
|
Error(String),
|
||||||
Render(Option<String>),
|
Render(Option<String>),
|
||||||
|
|
@ -35,6 +33,17 @@ pub enum ClientInstruction {
|
||||||
ServerError(String),
|
ServerError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ServerToClientMsg> for ClientInstruction {
|
||||||
|
fn from(instruction: ServerToClientMsg) -> Self {
|
||||||
|
match instruction {
|
||||||
|
ServerToClientMsg::Exit => ClientInstruction::Exit,
|
||||||
|
ServerToClientMsg::Render(buffer) => ClientInstruction::Render(buffer),
|
||||||
|
ServerToClientMsg::UnblockInputThread => ClientInstruction::UnblockInputThread,
|
||||||
|
ServerToClientMsg::ServerError(backtrace) => ClientInstruction::ServerError(backtrace),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_server(socket_path: &Path) -> io::Result<()> {
|
fn spawn_server(socket_path: &Path) -> io::Result<()> {
|
||||||
let status = Command::new(current_exe()?)
|
let status = Command::new(current_exe()?)
|
||||||
.arg("--server")
|
.arg("--server")
|
||||||
|
|
@ -71,7 +80,7 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs, config: C
|
||||||
|
|
||||||
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
|
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
|
||||||
os_input.connect_to_server(&*ZELLIJ_IPC_PIPE);
|
os_input.connect_to_server(&*ZELLIJ_IPC_PIPE);
|
||||||
os_input.send_to_server(ServerInstruction::NewClient(full_screen_ws, opts));
|
os_input.send_to_server(ClientToServerMsg::NewClient(full_screen_ws, opts));
|
||||||
os_input.set_raw_mode(0);
|
os_input.set_raw_mode(0);
|
||||||
let _ = os_input
|
let _ = os_input
|
||||||
.get_stdout_writer()
|
.get_stdout_writer()
|
||||||
|
|
@ -117,7 +126,7 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs, config: C
|
||||||
os_input.receive_sigwinch(Box::new({
|
os_input.receive_sigwinch(Box::new({
|
||||||
let os_api = os_input.clone();
|
let os_api = os_input.clone();
|
||||||
move || {
|
move || {
|
||||||
os_api.send_to_server(ServerInstruction::TerminalResize(
|
os_api.send_to_server(ClientToServerMsg::TerminalResize(
|
||||||
os_api.get_terminal_size_using_fd(0),
|
os_api.get_terminal_size_using_fd(0),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
@ -132,15 +141,15 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs, config: C
|
||||||
let os_input = os_input.clone();
|
let os_input = os_input.clone();
|
||||||
let mut should_break = false;
|
let mut should_break = false;
|
||||||
move || loop {
|
move || loop {
|
||||||
let (instruction, mut err_ctx) = os_input.recv_from_server();
|
let (instruction, err_ctx) = os_input.recv_from_server();
|
||||||
err_ctx.add_call(ContextType::Client(ClientContext::from(&instruction)));
|
err_ctx.update_thread_ctx();
|
||||||
match instruction {
|
match instruction {
|
||||||
ClientInstruction::Exit | ClientInstruction::ServerError(_) => {
|
ServerToClientMsg::Exit | ServerToClientMsg::ServerError(_) => {
|
||||||
should_break = true;
|
should_break = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
send_client_instructions.send(instruction).unwrap();
|
send_client_instructions.send(instruction.into()).unwrap();
|
||||||
if should_break {
|
if should_break {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -168,13 +177,11 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs, config: C
|
||||||
.recv()
|
.recv()
|
||||||
.expect("failed to receive app instruction on channel");
|
.expect("failed to receive app instruction on channel");
|
||||||
|
|
||||||
err_ctx.add_call(ContextType::Client(ClientContext::from(
|
err_ctx.add_call(ContextType::Client((&client_instruction).into()));
|
||||||
&client_instruction,
|
|
||||||
)));
|
|
||||||
match client_instruction {
|
match client_instruction {
|
||||||
ClientInstruction::Exit => break,
|
ClientInstruction::Exit => break,
|
||||||
ClientInstruction::Error(backtrace) => {
|
ClientInstruction::Error(backtrace) => {
|
||||||
let _ = os_input.send_to_server(ServerInstruction::ClientExit);
|
let _ = os_input.send_to_server(ClientToServerMsg::ClientExit);
|
||||||
handle_error(backtrace);
|
handle_error(backtrace);
|
||||||
}
|
}
|
||||||
ClientInstruction::ServerError(backtrace) => {
|
ClientInstruction::ServerError(backtrace) => {
|
||||||
|
|
@ -196,7 +203,7 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs, config: C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = os_input.send_to_server(ServerInstruction::ClientExit);
|
let _ = os_input.send_to_server(ClientToServerMsg::ClientExit);
|
||||||
router_thread.join().unwrap();
|
router_thread.join().unwrap();
|
||||||
|
|
||||||
// cleanup();
|
// cleanup();
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,11 @@ impl ErrorContext {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.update_thread_ctx()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the thread local [`ErrorContext`].
|
||||||
|
pub fn update_thread_ctx(&self) {
|
||||||
ASYNCOPENCALLS
|
ASYNCOPENCALLS
|
||||||
.try_with(|ctx| *ctx.borrow_mut() = *self)
|
.try_with(|ctx| *ctx.borrow_mut() = *self)
|
||||||
.unwrap_or_else(|_| OPENCALLS.with(|ctx| *ctx.borrow_mut() = *self));
|
.unwrap_or_else(|_| OPENCALLS.with(|ctx| *ctx.borrow_mut() = *self));
|
||||||
|
|
@ -369,9 +374,7 @@ impl From<&ClientInstruction> for ClientContext {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum ServerContext {
|
pub enum ServerContext {
|
||||||
NewClient,
|
NewClient,
|
||||||
Action,
|
|
||||||
Render,
|
Render,
|
||||||
TerminalResize,
|
|
||||||
UnblockInputThread,
|
UnblockInputThread,
|
||||||
ClientExit,
|
ClientExit,
|
||||||
Error,
|
Error,
|
||||||
|
|
@ -381,8 +384,6 @@ impl From<&ServerInstruction> for ServerContext {
|
||||||
fn from(server_instruction: &ServerInstruction) -> Self {
|
fn from(server_instruction: &ServerInstruction) -> Self {
|
||||||
match *server_instruction {
|
match *server_instruction {
|
||||||
ServerInstruction::NewClient(..) => ServerContext::NewClient,
|
ServerInstruction::NewClient(..) => ServerContext::NewClient,
|
||||||
ServerInstruction::Action(_) => ServerContext::Action,
|
|
||||||
ServerInstruction::TerminalResize(_) => ServerContext::TerminalResize,
|
|
||||||
ServerInstruction::Render(_) => ServerContext::Render,
|
ServerInstruction::Render(_) => ServerContext::Render,
|
||||||
ServerInstruction::UnblockInputThread => ServerContext::UnblockInputThread,
|
ServerInstruction::UnblockInputThread => ServerContext::UnblockInputThread,
|
||||||
ServerInstruction::ClientExit => ServerContext::ClientExit,
|
ServerInstruction::ClientExit => ServerContext::ClientExit,
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ use super::actions::Action;
|
||||||
use super::keybinds::Keybinds;
|
use super::keybinds::Keybinds;
|
||||||
use crate::client::ClientInstruction;
|
use crate::client::ClientInstruction;
|
||||||
use crate::common::input::config::Config;
|
use crate::common::input::config::Config;
|
||||||
|
use crate::common::ipc::ClientToServerMsg;
|
||||||
use crate::common::thread_bus::{SenderWithContext, OPENCALLS};
|
use crate::common::thread_bus::{SenderWithContext, OPENCALLS};
|
||||||
use crate::errors::ContextType;
|
use crate::errors::ContextType;
|
||||||
use crate::os_input_output::ClientOsApi;
|
use crate::os_input_output::ClientOsApi;
|
||||||
use crate::server::ServerInstruction;
|
|
||||||
use crate::CommandIsExecuting;
|
use crate::CommandIsExecuting;
|
||||||
|
|
||||||
use termion::input::{TermRead, TermReadEventsAndRaw};
|
use termion::input::{TermRead, TermReadEventsAndRaw};
|
||||||
|
|
@ -139,7 +139,7 @@ impl InputHandler {
|
||||||
Action::SwitchToMode(mode) => {
|
Action::SwitchToMode(mode) => {
|
||||||
self.mode = mode;
|
self.mode = mode;
|
||||||
self.os_input
|
self.os_input
|
||||||
.send_to_server(ServerInstruction::Action(action));
|
.send_to_server(ClientToServerMsg::Action(action));
|
||||||
}
|
}
|
||||||
Action::CloseFocus
|
Action::CloseFocus
|
||||||
| Action::NewPane(_)
|
| Action::NewPane(_)
|
||||||
|
|
@ -151,13 +151,13 @@ impl InputHandler {
|
||||||
| Action::MoveFocusOrTab(_) => {
|
| Action::MoveFocusOrTab(_) => {
|
||||||
self.command_is_executing.blocking_input_thread();
|
self.command_is_executing.blocking_input_thread();
|
||||||
self.os_input
|
self.os_input
|
||||||
.send_to_server(ServerInstruction::Action(action));
|
.send_to_server(ClientToServerMsg::Action(action));
|
||||||
self.command_is_executing
|
self.command_is_executing
|
||||||
.wait_until_input_thread_is_unblocked();
|
.wait_until_input_thread_is_unblocked();
|
||||||
}
|
}
|
||||||
_ => self
|
_ => self
|
||||||
.os_input
|
.os_input
|
||||||
.send_to_server(ServerInstruction::Action(action)),
|
.send_to_server(ClientToServerMsg::Action(action)),
|
||||||
}
|
}
|
||||||
|
|
||||||
should_break
|
should_break
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
//! IPC stuff for starting to split things into a client and server model.
|
//! IPC stuff for starting to split things into a client and server model.
|
||||||
|
|
||||||
use crate::common::errors::{get_current_ctx, ErrorContext};
|
use crate::cli::CliArgs;
|
||||||
|
use crate::common::{
|
||||||
|
errors::{get_current_ctx, ErrorContext},
|
||||||
|
input::actions::Action,
|
||||||
|
};
|
||||||
|
use crate::panes::PositionAndSize;
|
||||||
use interprocess::local_socket::LocalSocketStream;
|
use interprocess::local_socket::LocalSocketStream;
|
||||||
use nix::unistd::dup;
|
use nix::unistd::dup;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::os::unix::io::{AsRawFd, FromRawFd};
|
use std::os::unix::io::{AsRawFd, FromRawFd};
|
||||||
|
|
@ -29,9 +33,9 @@ pub enum ClientType {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Types of messages sent from the client to the server
|
// Types of messages sent from the client to the server
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum _ClientToServerMsg {
|
pub enum ClientToServerMsg {
|
||||||
// List which sessions are available
|
/*// List which sessions are available
|
||||||
ListSessions,
|
ListSessions,
|
||||||
// Create a new session
|
// Create a new session
|
||||||
CreateSession,
|
CreateSession,
|
||||||
|
|
@ -40,16 +44,24 @@ pub enum _ClientToServerMsg {
|
||||||
// Force detach
|
// Force detach
|
||||||
DetachSession(SessionId),
|
DetachSession(SessionId),
|
||||||
// Disconnect from the session we're connected to
|
// Disconnect from the session we're connected to
|
||||||
DisconnectFromSession,
|
DisconnectFromSession,*/
|
||||||
|
ClientExit,
|
||||||
|
TerminalResize(PositionAndSize),
|
||||||
|
NewClient(PositionAndSize, CliArgs),
|
||||||
|
Action(Action),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Types of messages sent from the server to the client
|
// Types of messages sent from the server to the client
|
||||||
// @@@ Implement Serialize and Deserialize for this...
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum _ServerToClientMsg {
|
pub enum ServerToClientMsg {
|
||||||
// Info about a particular session
|
/*// Info about a particular session
|
||||||
SessionInfo(Session),
|
SessionInfo(Session),
|
||||||
// A list of sessions
|
// A list of sessions
|
||||||
SessionList(HashSet<Session>),
|
SessionList(HashSet<Session>),*/
|
||||||
|
Render(Option<String>),
|
||||||
|
UnblockInputThread,
|
||||||
|
Exit,
|
||||||
|
ServerError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends messages on a stream socket, along with an [`ErrorContext`].
|
/// Sends messages on a stream socket, along with an [`ErrorContext`].
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::client::ClientInstruction;
|
use crate::common::ipc::{
|
||||||
use crate::common::ipc::{IpcReceiverWithContext, IpcSenderWithContext};
|
ClientToServerMsg, IpcReceiverWithContext, IpcSenderWithContext, ServerToClientMsg,
|
||||||
|
};
|
||||||
use crate::errors::ErrorContext;
|
use crate::errors::ErrorContext;
|
||||||
use crate::panes::PositionAndSize;
|
use crate::panes::PositionAndSize;
|
||||||
use crate::server::ServerInstruction;
|
|
||||||
use crate::utils::shared::default_palette;
|
use crate::utils::shared::default_palette;
|
||||||
use interprocess::local_socket::LocalSocketStream;
|
use interprocess::local_socket::LocalSocketStream;
|
||||||
use nix::fcntl::{fcntl, FcntlArg, OFlag};
|
use nix::fcntl::{fcntl, FcntlArg, OFlag};
|
||||||
|
|
@ -167,8 +167,8 @@ fn spawn_terminal(file_to_open: Option<PathBuf>, orig_termios: termios::Termios)
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ServerOsInputOutput {
|
pub struct ServerOsInputOutput {
|
||||||
orig_termios: Arc<Mutex<termios::Termios>>,
|
orig_termios: Arc<Mutex<termios::Termios>>,
|
||||||
receive_instructions_from_client: Option<Arc<Mutex<IpcReceiverWithContext<ServerInstruction>>>>,
|
receive_instructions_from_client: Option<Arc<Mutex<IpcReceiverWithContext<ClientToServerMsg>>>>,
|
||||||
send_instructions_to_client: Arc<Mutex<Option<IpcSenderWithContext<ClientInstruction>>>>,
|
send_instructions_to_client: Arc<Mutex<Option<IpcSenderWithContext<ServerToClientMsg>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `ServerOsApi` trait represents an abstract interface to the features of an operating system that
|
/// The `ServerOsApi` trait represents an abstract interface to the features of an operating system that
|
||||||
|
|
@ -192,9 +192,9 @@ pub trait ServerOsApi: Send + Sync {
|
||||||
/// Returns a [`Box`] pointer to this [`ServerOsApi`] struct.
|
/// Returns a [`Box`] pointer to this [`ServerOsApi`] struct.
|
||||||
fn box_clone(&self) -> Box<dyn ServerOsApi>;
|
fn box_clone(&self) -> Box<dyn ServerOsApi>;
|
||||||
/// Receives a message on server-side IPC channel
|
/// Receives a message on server-side IPC channel
|
||||||
fn recv_from_client(&self) -> (ServerInstruction, ErrorContext);
|
fn recv_from_client(&self) -> (ClientToServerMsg, ErrorContext);
|
||||||
/// Sends a message to client
|
/// Sends a message to client
|
||||||
fn send_to_client(&self, msg: ClientInstruction);
|
fn send_to_client(&self, msg: ServerToClientMsg);
|
||||||
/// Adds a sender to client
|
/// Adds a sender to client
|
||||||
fn add_client_sender(&mut self);
|
fn add_client_sender(&mut self);
|
||||||
/// Update the receiver socket for the client
|
/// Update the receiver socket for the client
|
||||||
|
|
@ -233,7 +233,7 @@ impl ServerOsApi for ServerOsInputOutput {
|
||||||
waitpid(Pid::from_raw(pid), None).unwrap();
|
waitpid(Pid::from_raw(pid), None).unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn recv_from_client(&self) -> (ServerInstruction, ErrorContext) {
|
fn recv_from_client(&self) -> (ClientToServerMsg, ErrorContext) {
|
||||||
self.receive_instructions_from_client
|
self.receive_instructions_from_client
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -241,7 +241,7 @@ impl ServerOsApi for ServerOsInputOutput {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.recv()
|
.recv()
|
||||||
}
|
}
|
||||||
fn send_to_client(&self, msg: ClientInstruction) {
|
fn send_to_client(&self, msg: ServerToClientMsg) {
|
||||||
self.send_instructions_to_client
|
self.send_instructions_to_client
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -288,8 +288,8 @@ pub fn get_server_os_input() -> ServerOsInputOutput {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ClientOsInputOutput {
|
pub struct ClientOsInputOutput {
|
||||||
orig_termios: Arc<Mutex<termios::Termios>>,
|
orig_termios: Arc<Mutex<termios::Termios>>,
|
||||||
send_instructions_to_server: Arc<Mutex<Option<IpcSenderWithContext<ServerInstruction>>>>,
|
send_instructions_to_server: Arc<Mutex<Option<IpcSenderWithContext<ClientToServerMsg>>>>,
|
||||||
receive_instructions_from_server: Arc<Mutex<Option<IpcReceiverWithContext<ClientInstruction>>>>,
|
receive_instructions_from_server: Arc<Mutex<Option<IpcReceiverWithContext<ServerToClientMsg>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `ClientOsApi` trait represents an abstract interface to the features of an operating system that
|
/// The `ClientOsApi` trait represents an abstract interface to the features of an operating system that
|
||||||
|
|
@ -310,10 +310,10 @@ pub trait ClientOsApi: Send + Sync {
|
||||||
/// Returns a [`Box`] pointer to this [`ClientOsApi`] struct.
|
/// Returns a [`Box`] pointer to this [`ClientOsApi`] struct.
|
||||||
fn box_clone(&self) -> Box<dyn ClientOsApi>;
|
fn box_clone(&self) -> Box<dyn ClientOsApi>;
|
||||||
/// Sends a message to the server.
|
/// Sends a message to the server.
|
||||||
fn send_to_server(&self, msg: ServerInstruction);
|
fn send_to_server(&self, msg: ClientToServerMsg);
|
||||||
/// Receives a message on client-side IPC channel
|
/// Receives a message on client-side IPC channel
|
||||||
// This should be called from the client-side router thread only.
|
// This should be called from the client-side router thread only.
|
||||||
fn recv_from_server(&self) -> (ClientInstruction, ErrorContext);
|
fn recv_from_server(&self) -> (ServerToClientMsg, ErrorContext);
|
||||||
fn receive_sigwinch(&self, cb: Box<dyn Fn()>);
|
fn receive_sigwinch(&self, cb: Box<dyn Fn()>);
|
||||||
/// Establish a connection with the server socket.
|
/// Establish a connection with the server socket.
|
||||||
fn connect_to_server(&self, path: &Path);
|
fn connect_to_server(&self, path: &Path);
|
||||||
|
|
@ -346,7 +346,7 @@ impl ClientOsApi for ClientOsInputOutput {
|
||||||
let stdout = ::std::io::stdout();
|
let stdout = ::std::io::stdout();
|
||||||
Box::new(stdout)
|
Box::new(stdout)
|
||||||
}
|
}
|
||||||
fn send_to_server(&self, msg: ServerInstruction) {
|
fn send_to_server(&self, msg: ClientToServerMsg) {
|
||||||
self.send_instructions_to_server
|
self.send_instructions_to_server
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -354,7 +354,7 @@ impl ClientOsApi for ClientOsInputOutput {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.send(msg);
|
.send(msg);
|
||||||
}
|
}
|
||||||
fn recv_from_server(&self) -> (ClientInstruction, ErrorContext) {
|
fn recv_from_server(&self) -> (ServerToClientMsg, ErrorContext) {
|
||||||
self.receive_instructions_from_server
|
self.receive_instructions_from_server
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use std::pin::*;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crate::client::panes::PaneId;
|
use crate::client::panes::PaneId;
|
||||||
use crate::common::errors::{get_current_ctx, ContextType, PtyContext};
|
use crate::common::errors::{get_current_ctx, ContextType};
|
||||||
use crate::common::screen::ScreenInstruction;
|
use crate::common::screen::ScreenInstruction;
|
||||||
use crate::common::thread_bus::{Bus, ThreadSenders};
|
use crate::common::thread_bus::{Bus, ThreadSenders};
|
||||||
use crate::layout::Layout;
|
use crate::layout::Layout;
|
||||||
|
|
@ -87,7 +87,7 @@ pub struct Pty {
|
||||||
pub fn pty_thread_main(mut pty: Pty, maybe_layout: Option<Layout>) {
|
pub fn pty_thread_main(mut pty: Pty, maybe_layout: Option<Layout>) {
|
||||||
loop {
|
loop {
|
||||||
let (event, mut err_ctx) = pty.bus.recv().expect("failed to receive event on channel");
|
let (event, mut err_ctx) = pty.bus.recv().expect("failed to receive event on channel");
|
||||||
err_ctx.add_call(ContextType::Pty(PtyContext::from(&event)));
|
err_ctx.add_call(ContextType::Pty((&event).into()));
|
||||||
match event {
|
match event {
|
||||||
PtyInstruction::SpawnTerminal(file_to_open) => {
|
PtyInstruction::SpawnTerminal(file_to_open) => {
|
||||||
let pid = pty.spawn_terminal(file_to_open);
|
let pid = pty.spawn_terminal(file_to_open);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use std::str;
|
||||||
use crate::common::input::options::Options;
|
use crate::common::input::options::Options;
|
||||||
use crate::common::pty::{PtyInstruction, VteBytes};
|
use crate::common::pty::{PtyInstruction, VteBytes};
|
||||||
use crate::common::thread_bus::Bus;
|
use crate::common::thread_bus::Bus;
|
||||||
use crate::errors::{ContextType, ScreenContext};
|
use crate::errors::ContextType;
|
||||||
use crate::layout::Layout;
|
use crate::layout::Layout;
|
||||||
use crate::panes::PaneId;
|
use crate::panes::PaneId;
|
||||||
use crate::panes::PositionAndSize;
|
use crate::panes::PositionAndSize;
|
||||||
|
|
@ -353,7 +353,7 @@ pub fn screen_thread_main(
|
||||||
.bus
|
.bus
|
||||||
.recv()
|
.recv()
|
||||||
.expect("failed to receive event on channel");
|
.expect("failed to receive event on channel");
|
||||||
err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event)));
|
err_ctx.add_call(ContextType::Screen((&event).into()));
|
||||||
match event {
|
match event {
|
||||||
ScreenInstruction::PtyBytes(pid, vte_bytes) => {
|
ScreenInstruction::PtyBytes(pid, vte_bytes) => {
|
||||||
let active_tab = screen.get_active_tab_mut().unwrap();
|
let active_tab = screen.get_active_tab_mut().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use wasmer::{
|
||||||
use wasmer_wasi::{Pipe, WasiEnv, WasiState};
|
use wasmer_wasi::{Pipe, WasiEnv, WasiState};
|
||||||
use zellij_tile::data::{Event, EventType, PluginIds};
|
use zellij_tile::data::{Event, EventType, PluginIds};
|
||||||
|
|
||||||
use crate::common::errors::{ContextType, PluginContext};
|
use crate::common::errors::ContextType;
|
||||||
use crate::common::pty::PtyInstruction;
|
use crate::common::pty::PtyInstruction;
|
||||||
use crate::common::screen::ScreenInstruction;
|
use crate::common::screen::ScreenInstruction;
|
||||||
use crate::common::thread_bus::{Bus, ThreadSenders};
|
use crate::common::thread_bus::{Bus, ThreadSenders};
|
||||||
|
|
@ -44,7 +44,7 @@ pub fn wasm_thread_main(bus: Bus<PluginInstruction>, store: Store, data_dir: Pat
|
||||||
let mut plugin_map = HashMap::new();
|
let mut plugin_map = HashMap::new();
|
||||||
loop {
|
loop {
|
||||||
let (event, mut err_ctx) = bus.recv().expect("failed to receive event on channel");
|
let (event, mut err_ctx) = bus.recv().expect("failed to receive event on channel");
|
||||||
err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event)));
|
err_ctx.add_call(ContextType::Plugin((&event).into()));
|
||||||
match event {
|
match event {
|
||||||
PluginInstruction::Load(pid_tx, path) => {
|
PluginInstruction::Load(pid_tx, path) => {
|
||||||
let plugin_dir = data_dir.join("plugins/");
|
let plugin_dir = data_dir.join("plugins/");
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ pub mod route;
|
||||||
|
|
||||||
use daemonize::Daemonize;
|
use daemonize::Daemonize;
|
||||||
use interprocess::local_socket::LocalSocketListener;
|
use interprocess::local_socket::LocalSocketListener;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::{path::PathBuf, sync::mpsc};
|
use std::{path::PathBuf, sync::mpsc};
|
||||||
|
|
@ -10,11 +9,10 @@ use wasmer::Store;
|
||||||
use zellij_tile::data::PluginCapabilities;
|
use zellij_tile::data::PluginCapabilities;
|
||||||
|
|
||||||
use crate::cli::CliArgs;
|
use crate::cli::CliArgs;
|
||||||
use crate::client::ClientInstruction;
|
|
||||||
use crate::common::thread_bus::{Bus, ThreadSenders};
|
use crate::common::thread_bus::{Bus, ThreadSenders};
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
errors::{ContextType, ServerContext},
|
errors::ContextType,
|
||||||
input::{actions::Action, options::Options},
|
ipc::{ClientToServerMsg, ServerToClientMsg},
|
||||||
os_input_output::{set_permissions, ServerOsApi},
|
os_input_output::{set_permissions, ServerOsApi},
|
||||||
pty::{pty_thread_main, Pty, PtyInstruction},
|
pty::{pty_thread_main, Pty, PtyInstruction},
|
||||||
screen::{screen_thread_main, ScreenInstruction},
|
screen::{screen_thread_main, ScreenInstruction},
|
||||||
|
|
@ -29,17 +27,25 @@ use route::route_thread_main;
|
||||||
|
|
||||||
/// Instructions related to server-side application including the
|
/// Instructions related to server-side application including the
|
||||||
/// ones sent by client to server
|
/// ones sent by client to server
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ServerInstruction {
|
pub enum ServerInstruction {
|
||||||
TerminalResize(PositionAndSize),
|
NewClient(PositionAndSize, CliArgs),
|
||||||
NewClient(PositionAndSize, CliArgs, Options),
|
|
||||||
Action(Action),
|
|
||||||
Render(Option<String>),
|
Render(Option<String>),
|
||||||
UnblockInputThread,
|
UnblockInputThread,
|
||||||
ClientExit,
|
ClientExit,
|
||||||
Error(String),
|
Error(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ClientToServerMsg> for ServerInstruction {
|
||||||
|
fn from(instruction: ClientToServerMsg) -> Self {
|
||||||
|
match instruction {
|
||||||
|
ClientToServerMsg::ClientExit => ServerInstruction::ClientExit,
|
||||||
|
ClientToServerMsg::NewClient(pos, opts) => ServerInstruction::NewClient(pos, opts),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SessionMetaData {
|
pub struct SessionMetaData {
|
||||||
pub senders: ThreadSenders,
|
pub senders: ThreadSenders,
|
||||||
screen_thread: Option<thread::JoinHandle<()>>,
|
screen_thread: Option<thread::JoinHandle<()>>,
|
||||||
|
|
@ -65,6 +71,8 @@ pub fn start_server(os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
|
||||||
.start()
|
.start()
|
||||||
.expect("could not daemonize the server process");
|
.expect("could not daemonize the server process");
|
||||||
|
|
||||||
|
std::env::set_var(&"ZELLIJ", "0");
|
||||||
|
|
||||||
let (to_server, server_receiver): SyncChannelWithContext<ServerInstruction> =
|
let (to_server, server_receiver): SyncChannelWithContext<ServerInstruction> =
|
||||||
mpsc::sync_channel(50);
|
mpsc::sync_channel(50);
|
||||||
let to_server = SenderWithContext::new(SenderType::SyncSender(to_server));
|
let to_server = SenderWithContext::new(SenderType::SyncSender(to_server));
|
||||||
|
|
@ -140,7 +148,7 @@ pub fn start_server(os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (instruction, mut err_ctx) = server_receiver.recv().unwrap();
|
let (instruction, mut err_ctx) = server_receiver.recv().unwrap();
|
||||||
err_ctx.add_call(ContextType::IPCServer(ServerContext::from(&instruction)));
|
err_ctx.add_call(ContextType::IPCServer((&instruction).into()));
|
||||||
match instruction {
|
match instruction {
|
||||||
ServerInstruction::NewClient(full_screen_ws, opts) => {
|
ServerInstruction::NewClient(full_screen_ws, opts) => {
|
||||||
let session_data =
|
let session_data =
|
||||||
|
|
@ -156,21 +164,20 @@ pub fn start_server(os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
ServerInstruction::UnblockInputThread => {
|
ServerInstruction::UnblockInputThread => {
|
||||||
os_input.send_to_client(ClientInstruction::UnblockInputThread);
|
os_input.send_to_client(ServerToClientMsg::UnblockInputThread);
|
||||||
}
|
}
|
||||||
ServerInstruction::ClientExit => {
|
ServerInstruction::ClientExit => {
|
||||||
*sessions.write().unwrap() = None;
|
*sessions.write().unwrap() = None;
|
||||||
os_input.send_to_client(ClientInstruction::Exit);
|
os_input.send_to_client(ServerToClientMsg::Exit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ServerInstruction::Render(output) => {
|
ServerInstruction::Render(output) => {
|
||||||
os_input.send_to_client(ClientInstruction::Render(output))
|
os_input.send_to_client(ServerToClientMsg::Render(output))
|
||||||
}
|
}
|
||||||
ServerInstruction::Error(backtrace) => {
|
ServerInstruction::Error(backtrace) => {
|
||||||
os_input.send_to_client(ClientInstruction::ServerError(backtrace));
|
os_input.send_to_client(ServerToClientMsg::ServerError(backtrace));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_ => panic!("Received unexpected instruction."),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drop(std::fs::remove_file(&socket_path));
|
drop(std::fs::remove_file(&socket_path));
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use zellij_tile::data::{Event, PluginCapabilities};
|
use zellij_tile::data::{Event, PluginCapabilities};
|
||||||
|
|
||||||
use crate::common::errors::{ContextType, ServerContext};
|
|
||||||
use crate::common::input::actions::{Action, Direction};
|
use crate::common::input::actions::{Action, Direction};
|
||||||
use crate::common::input::handler::get_mode_info;
|
use crate::common::input::handler::get_mode_info;
|
||||||
|
use crate::common::ipc::ClientToServerMsg;
|
||||||
use crate::common::os_input_output::ServerOsApi;
|
use crate::common::os_input_output::ServerOsApi;
|
||||||
use crate::common::pty::PtyInstruction;
|
use crate::common::pty::PtyInstruction;
|
||||||
use crate::common::screen::ScreenInstruction;
|
use crate::common::screen::ScreenInstruction;
|
||||||
|
|
@ -193,23 +193,18 @@ pub fn route_thread_main(
|
||||||
capabilities: PluginCapabilities,
|
capabilities: PluginCapabilities,
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
let (instruction, mut err_ctx) = os_input.recv_from_client();
|
let (instruction, err_ctx) = os_input.recv_from_client();
|
||||||
err_ctx.add_call(ContextType::IPCServer(ServerContext::from(&instruction)));
|
err_ctx.update_thread_ctx();
|
||||||
let rlocked_sessions = sessions.read().unwrap();
|
let rlocked_sessions = sessions.read().unwrap();
|
||||||
match instruction {
|
match instruction {
|
||||||
ServerInstruction::ClientExit => {
|
ClientToServerMsg::ClientExit => {
|
||||||
to_server.send(instruction).unwrap();
|
to_server.send(instruction.into()).unwrap();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ServerInstruction::Action(action) => {
|
ClientToServerMsg::Action(action) => {
|
||||||
route_action(
|
route_action(action, rlocked_sessions.as_ref().unwrap(), &*os_input);
|
||||||
action,
|
|
||||||
rlocked_sessions.as_ref().unwrap(),
|
|
||||||
&*os_input,
|
|
||||||
capabilities,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
ServerInstruction::TerminalResize(new_size) => {
|
ClientToServerMsg::TerminalResize(new_size) => {
|
||||||
rlocked_sessions
|
rlocked_sessions
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -217,12 +212,9 @@ pub fn route_thread_main(
|
||||||
.send_to_screen(ScreenInstruction::TerminalResize(new_size))
|
.send_to_screen(ScreenInstruction::TerminalResize(new_size))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
ServerInstruction::NewClient(..) => {
|
ClientToServerMsg::NewClient(..) => {
|
||||||
os_input.add_client_sender();
|
os_input.add_client_sender();
|
||||||
to_server.send(instruction).unwrap();
|
to_server.send(instruction.into()).unwrap();
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
to_server.send(instruction).unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,10 @@ use std::path::PathBuf;
|
||||||
use std::sync::{mpsc, Arc, Condvar, Mutex};
|
use std::sync::{mpsc, Arc, Condvar, Mutex};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crate::client::ClientInstruction;
|
use crate::common::ipc::{ClientToServerMsg, ServerToClientMsg};
|
||||||
use crate::common::thread_bus::{ChannelWithContext, SenderType, SenderWithContext};
|
use crate::common::thread_bus::{ChannelWithContext, SenderType, SenderWithContext};
|
||||||
use crate::errors::ErrorContext;
|
use crate::errors::ErrorContext;
|
||||||
use crate::os_input_output::{ClientOsApi, ServerOsApi};
|
use crate::os_input_output::{ClientOsApi, ServerOsApi};
|
||||||
use crate::server::ServerInstruction;
|
|
||||||
use crate::tests::possible_tty_inputs::{get_possible_tty_inputs, Bytes};
|
use crate::tests::possible_tty_inputs::{get_possible_tty_inputs, Bytes};
|
||||||
use crate::tests::utils::commands::{QUIT, SLEEP};
|
use crate::tests::utils::commands::{QUIT, SLEEP};
|
||||||
use crate::utils::shared::default_palette;
|
use crate::utils::shared::default_palette;
|
||||||
|
|
@ -77,10 +76,10 @@ pub struct FakeInputOutput {
|
||||||
win_sizes: Arc<Mutex<HashMap<RawFd, PositionAndSize>>>,
|
win_sizes: Arc<Mutex<HashMap<RawFd, PositionAndSize>>>,
|
||||||
possible_tty_inputs: HashMap<u16, Bytes>,
|
possible_tty_inputs: HashMap<u16, Bytes>,
|
||||||
last_snapshot_time: Arc<Mutex<Instant>>,
|
last_snapshot_time: Arc<Mutex<Instant>>,
|
||||||
send_instructions_to_client: SenderWithContext<ClientInstruction>,
|
send_instructions_to_client: SenderWithContext<ServerToClientMsg>,
|
||||||
receive_instructions_from_server: Arc<Mutex<mpsc::Receiver<(ClientInstruction, ErrorContext)>>>,
|
receive_instructions_from_server: Arc<Mutex<mpsc::Receiver<(ServerToClientMsg, ErrorContext)>>>,
|
||||||
send_instructions_to_server: SenderWithContext<ServerInstruction>,
|
send_instructions_to_server: SenderWithContext<ClientToServerMsg>,
|
||||||
receive_instructions_from_client: Arc<Mutex<mpsc::Receiver<(ServerInstruction, ErrorContext)>>>,
|
receive_instructions_from_client: Arc<Mutex<mpsc::Receiver<(ClientToServerMsg, ErrorContext)>>>,
|
||||||
should_trigger_sigwinch: Arc<(Mutex<bool>, Condvar)>,
|
should_trigger_sigwinch: Arc<(Mutex<bool>, Condvar)>,
|
||||||
sigwinch_event: Option<PositionAndSize>,
|
sigwinch_event: Option<PositionAndSize>,
|
||||||
}
|
}
|
||||||
|
|
@ -90,10 +89,10 @@ impl FakeInputOutput {
|
||||||
let mut win_sizes = HashMap::new();
|
let mut win_sizes = HashMap::new();
|
||||||
let last_snapshot_time = Arc::new(Mutex::new(Instant::now()));
|
let last_snapshot_time = Arc::new(Mutex::new(Instant::now()));
|
||||||
let stdout_writer = FakeStdoutWriter::new(last_snapshot_time.clone());
|
let stdout_writer = FakeStdoutWriter::new(last_snapshot_time.clone());
|
||||||
let (client_sender, client_receiver): ChannelWithContext<ClientInstruction> =
|
let (client_sender, client_receiver): ChannelWithContext<ServerToClientMsg> =
|
||||||
mpsc::channel();
|
mpsc::channel();
|
||||||
let send_instructions_to_client = SenderWithContext::new(SenderType::Sender(client_sender));
|
let send_instructions_to_client = SenderWithContext::new(SenderType::Sender(client_sender));
|
||||||
let (server_sender, server_receiver): ChannelWithContext<ServerInstruction> =
|
let (server_sender, server_receiver): ChannelWithContext<ClientToServerMsg> =
|
||||||
mpsc::channel();
|
mpsc::channel();
|
||||||
let send_instructions_to_server = SenderWithContext::new(SenderType::Sender(server_sender));
|
let send_instructions_to_server = SenderWithContext::new(SenderType::Sender(server_sender));
|
||||||
win_sizes.insert(0, winsize); // 0 is the current terminal
|
win_sizes.insert(0, winsize); // 0 is the current terminal
|
||||||
|
|
@ -195,10 +194,10 @@ impl ClientOsApi for FakeInputOutput {
|
||||||
fn get_stdout_writer(&self) -> Box<dyn Write> {
|
fn get_stdout_writer(&self) -> Box<dyn Write> {
|
||||||
Box::new(self.stdout_writer.clone())
|
Box::new(self.stdout_writer.clone())
|
||||||
}
|
}
|
||||||
fn send_to_server(&self, msg: ServerInstruction) {
|
fn send_to_server(&self, msg: ClientToServerMsg) {
|
||||||
self.send_instructions_to_server.send(msg).unwrap();
|
self.send_instructions_to_server.send(msg).unwrap();
|
||||||
}
|
}
|
||||||
fn recv_from_server(&self) -> (ClientInstruction, ErrorContext) {
|
fn recv_from_server(&self) -> (ServerToClientMsg, ErrorContext) {
|
||||||
self.receive_instructions_from_server
|
self.receive_instructions_from_server
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -278,14 +277,14 @@ impl ServerOsApi for FakeInputOutput {
|
||||||
self.io_events.lock().unwrap().push(IoEvent::Kill(fd));
|
self.io_events.lock().unwrap().push(IoEvent::Kill(fd));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn recv_from_client(&self) -> (ServerInstruction, ErrorContext) {
|
fn recv_from_client(&self) -> (ClientToServerMsg, ErrorContext) {
|
||||||
self.receive_instructions_from_client
|
self.receive_instructions_from_client
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.recv()
|
.recv()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
fn send_to_client(&self, msg: ClientInstruction) {
|
fn send_to_client(&self, msg: ServerToClientMsg) {
|
||||||
self.send_instructions_to_client.send(msg).unwrap();
|
self.send_instructions_to_client.send(msg).unwrap();
|
||||||
}
|
}
|
||||||
fn add_client_sender(&mut self) {}
|
fn add_client_sender(&mut self) {}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue