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 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 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 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}