feat(ipc): server bind + Connection wrapper
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
pub mod client;
|
||||
pub mod envelope;
|
||||
pub mod framing;
|
||||
pub mod server;
|
||||
|
||||
pub use client::{Client, ClientError};
|
||||
pub use envelope::{
|
||||
@@ -10,3 +11,4 @@ pub use envelope::{
|
||||
RpcError,
|
||||
};
|
||||
pub use framing::JsonFramed;
|
||||
pub use server::{bind, Connection};
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
use crate::envelope::{Incoming, Notification, Response};
|
||||
use crate::framing::JsonFramed;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use tokio::net::{UnixListener, UnixStream};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
pub struct Connection {
|
||||
inner: Arc<Mutex<JsonFramed>>,
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
pub fn new(stream: UnixStream) -> Self {
|
||||
Self {
|
||||
inner: Arc::new(Mutex::new(JsonFramed::new(stream))),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn read_incoming(&self) -> std::io::Result<Option<Incoming>> {
|
||||
let mut g = self.inner.lock().await;
|
||||
g.read::<Incoming>().await
|
||||
}
|
||||
|
||||
pub async fn write_response(&self, r: &Response) -> std::io::Result<()> {
|
||||
let mut g = self.inner.lock().await;
|
||||
g.write(r).await
|
||||
}
|
||||
|
||||
pub async fn write_notification(&self, n: &Notification) -> std::io::Result<()> {
|
||||
let mut g = self.inner.lock().await;
|
||||
g.write(n).await
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind(socket_path: &Path) -> std::io::Result<UnixListener> {
|
||||
if socket_path.exists() {
|
||||
std::fs::remove_file(socket_path)?;
|
||||
}
|
||||
|
||||
if let Some(parent) = socket_path.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
|
||||
let listener = UnixListener::bind(socket_path)?;
|
||||
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
std::fs::set_permissions(socket_path, std::fs::Permissions::from_mode(0o600))?;
|
||||
|
||||
Ok(listener)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[tokio::test]
|
||||
async fn bind_creates_socket_with_0600() {
|
||||
let dir = tempdir().unwrap();
|
||||
let path = dir.path().join("x.sock");
|
||||
let _listener = bind(&path).unwrap();
|
||||
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mode = std::fs::metadata(&path).unwrap().permissions().mode() & 0o777;
|
||||
assert_eq!(mode, 0o600);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user