diff options
| author | sodiboo <37938646+sodiboo@users.noreply.github.com> | 2024-04-19 15:02:32 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-19 13:02:32 +0000 |
| commit | b5f7e4bd83dbfc77e0c8b973bc217c9a4cb3f364 (patch) | |
| tree | dbe59c9a19f2e7d94086e9fbb1c28a43e062e16b /niri-ipc/src | |
| parent | b98b95883def5cd726c1e96a006f9cd7498d1730 (diff) | |
| download | niri-b5f7e4bd83dbfc77e0c8b973bc217c9a4cb3f364.tar.gz niri-b5f7e4bd83dbfc77e0c8b973bc217c9a4cb3f364.tar.bz2 niri-b5f7e4bd83dbfc77e0c8b973bc217c9a4cb3f364.zip | |
`niri_ipc::Socket`; `niri msg version`; version checking on IPC (#278)
* Implement version checking in IPC
implement version checking; streamed IPC
streamed IPC will allow multiple requests per connection
add nonsense request
change inline struct to json macro
only check version if request actually fails
fix usage of inspect_err (MSRV 1.72.0; stabilized 1.76.0)
"nonsense request" -> "return error"
oneshot connections
* Change some things around
* Unqualify niri_ipc::Transform
---------
Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
Diffstat (limited to 'niri-ipc/src')
| -rw-r--r-- | niri-ipc/src/lib.rs | 10 | ||||
| -rw-r--r-- | niri-ipc/src/socket.rs | 63 |
2 files changed, 71 insertions, 2 deletions
diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs index 33d25f2d..26b89283 100644 --- a/niri-ipc/src/lib.rs +++ b/niri-ipc/src/lib.rs @@ -6,18 +6,22 @@ use std::str::FromStr; use serde::{Deserialize, Serialize}; -/// Name of the environment variable containing the niri IPC socket path. -pub const SOCKET_PATH_ENV: &str = "NIRI_SOCKET"; +mod socket; +pub use socket::{Socket, SOCKET_PATH_ENV}; /// Request from client to niri. #[derive(Debug, Serialize, Deserialize, Clone)] pub enum Request { + /// Request the version string for the running niri instance. + Version, /// Request information about connected outputs. Outputs, /// Request information about the focused window. FocusedWindow, /// Perform an action. Action(Action), + /// Respond with an error (for testing error handling). + ReturnError, } /// Reply from niri to client. @@ -35,6 +39,8 @@ pub type Reply = Result<Response, String>; pub enum Response { /// A request that does not need a response was handled successfully. Handled, + /// The version string for the running niri instance. + Version(String), /// Information about connected outputs. /// /// Map from connector name to output info. diff --git a/niri-ipc/src/socket.rs b/niri-ipc/src/socket.rs new file mode 100644 index 00000000..67b9625c --- /dev/null +++ b/niri-ipc/src/socket.rs @@ -0,0 +1,63 @@ +//! Helper for blocking communication over the niri socket. + +use std::env; +use std::io::{self, Read, Write}; +use std::net::Shutdown; +use std::os::unix::net::UnixStream; +use std::path::Path; + +use crate::{Reply, Request}; + +/// Name of the environment variable containing the niri IPC socket path. +pub const SOCKET_PATH_ENV: &str = "NIRI_SOCKET"; + +/// Helper for blocking communication over the niri socket. +/// +/// This struct is used to communicate with the niri IPC server. It handles the socket connection +/// and serialization/deserialization of messages. +pub struct Socket { + stream: UnixStream, +} + +impl Socket { + /// Connects to the default niri IPC socket. + /// + /// This is equivalent to calling [`Self::connect_to`] with the path taken from the + /// [`SOCKET_PATH_ENV`] environment variable. + pub fn connect() -> io::Result<Self> { + let socket_path = env::var_os(SOCKET_PATH_ENV).ok_or_else(|| { + io::Error::new( + io::ErrorKind::NotFound, + format!("{SOCKET_PATH_ENV} is not set, are you running this within niri?"), + ) + })?; + Self::connect_to(socket_path) + } + + /// Connects to the niri IPC socket at the given path. + pub fn connect_to(path: impl AsRef<Path>) -> io::Result<Self> { + let stream = UnixStream::connect(path.as_ref())?; + Ok(Self { stream }) + } + + /// Sends a request to niri and returns the response. + /// + /// Return values: + /// + /// * `Ok(Ok(response))`: successful [`Response`](crate::Response) from niri + /// * `Ok(Err(message))`: error message from niri + /// * `Err(error)`: error communicating with niri + pub fn send(self, request: Request) -> io::Result<Reply> { + let Self { mut stream } = self; + + let mut buf = serde_json::to_vec(&request).unwrap(); + stream.write_all(&buf)?; + stream.shutdown(Shutdown::Write)?; + + buf.clear(); + stream.read_to_end(&mut buf)?; + + let reply = serde_json::from_slice(&buf)?; + Ok(reply) + } +} |
