Skip to main content

libsession_rs/
lib.rs

1use std::os::fd;
2use std::os::fd::{AsFd, AsRawFd};
3use std::{ffi, ptr, result};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum Error {
7    Failed,
8}
9
10type Result<T> = result::Result<T, Error>;
11
12pub struct Session(ptr::NonNull<libsession_sys::libsession_context>);
13
14impl Session {
15    #[must_use]
16    pub fn connect() -> Option<Self> {
17        ptr::NonNull::new(libsession_sys::libsession_new()).map(Self)
18    }
19
20    /// Retrieves the session ID for the current process.
21    ///
22    /// # Errors
23    ///
24    /// Returns `Error::Failed` if the backend cannot resolve the session or
25    /// returns a null session ID.
26    pub fn id(&self) -> Result<String> {
27        let mut id = ptr::null_mut();
28        result(unsafe { libsession_sys::libsession_get_session(self.0.as_ptr(), &raw mut id) })?;
29        unsafe { take_session_id(id) }
30    }
31
32    /// Retrieves the session ID for a process.
33    ///
34    /// # Errors
35    ///
36    /// Returns `Error::Failed` if `pid` is outside the platform's process ID
37    /// range, the backend cannot resolve the session, or it returns a null ID.
38    pub fn id_for_pid(&self, pid: u32) -> Result<String> {
39        let pid = pid.try_into().map_err(|_| Error::Failed)?;
40        let mut id = ptr::null_mut();
41        result(unsafe {
42            libsession_sys::libsession_pid_get_session(self.0.as_ptr(), pid, &raw mut id)
43        })?;
44        unsafe { take_session_id(id) }
45    }
46
47    /// Creates a monitor for session changes.
48    ///
49    /// # Errors
50    ///
51    /// Returns `Error::Failed` if the backend cannot create a monitor.
52    pub fn monitor(&mut self) -> Result<Monitor> {
53        ptr::NonNull::new(libsession_sys::libsession_monitor_new(self.0.as_ptr()))
54            .map(Monitor)
55            .ok_or(Error::Failed)
56    }
57}
58
59pub struct Monitor(ptr::NonNull<libsession_sys::libsession_monitor>);
60
61impl Monitor {
62    pub fn flush(&mut self) {
63        libsession_sys::libsession_monitor_flush(self.0.as_ptr());
64    }
65}
66
67impl AsRawFd for Monitor {
68    fn as_raw_fd(&self) -> fd::RawFd {
69        libsession_sys::libsession_monitor_fd(self.0.as_ptr())
70    }
71}
72
73impl AsFd for Monitor {
74    fn as_fd(&self) -> fd::BorrowedFd<'_> {
75        unsafe { fd::BorrowedFd::borrow_raw(self.as_raw_fd()) }
76    }
77}
78
79impl Drop for Monitor {
80    fn drop(&mut self) {
81        libsession_sys::libsession_monitor_free(self.0.as_ptr());
82    }
83}
84
85unsafe fn take_session_id(id: *mut ffi::c_char) -> Result<String> {
86    let id = ptr::NonNull::new(id).ok_or(Error::Failed)?;
87    let owned = unsafe { ffi::CStr::from_ptr(id.as_ptr()) }
88        .to_string_lossy()
89        .into_owned();
90    unsafe { libsession_sys::libsession_session_id_free(id.as_ptr()) };
91    Ok(owned)
92}
93
94const fn result(status: libsession_sys::LibsessionStatus) -> Result<()> {
95    match status {
96        libsession_sys::LibsessionStatus::Ok => Ok(()),
97        libsession_sys::LibsessionStatus::Failed => Err(Error::Failed),
98    }
99}
100
101impl Drop for Session {
102    fn drop(&mut self) {
103        libsession_sys::libsession_free(self.0.as_ptr());
104    }
105}