refactor + add doc + fix reload buf
This commit is contained in:
@@ -37,6 +37,15 @@ impl Configuration {
|
|||||||
/// * `Ok(Configuration)` if the configuration was successfully loaded and parsed.
|
/// * `Ok(Configuration)` if the configuration was successfully loaded and parsed.
|
||||||
/// * `Err(Box<dyn std::error::Error>)` if there was an error reading the file or
|
/// * `Err(Box<dyn std::error::Error>)` if there was an error reading the file or
|
||||||
/// parsing the TOML content.
|
/// parsing the TOML content.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use dysm_rs::configuration::Configuration;
|
||||||
|
/// use std::path::PathBuf;
|
||||||
|
///
|
||||||
|
/// let _ = Configuration::from(&PathBuf::from("references/daemon.conf")).unwrap();
|
||||||
|
/// ```
|
||||||
pub fn from(file: &PathBuf) -> Result<Self, Box<dyn std::error::Error>> {
|
pub fn from(file: &PathBuf) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
g_info!(
|
g_info!(
|
||||||
APPLICATION_NAME,
|
APPLICATION_NAME,
|
||||||
|
|||||||
210
src/session.rs
210
src/session.rs
@@ -1,13 +1,13 @@
|
|||||||
//! Session management for the display manager.
|
//! Session management for the display manager.
|
||||||
//!
|
//!
|
||||||
//! This module defines the `SessionManager` struct, which is responsible for
|
//! This module defines the `SessionManager` struct, which is responsible for
|
||||||
//! managing user sessions in the display manager. It includes functionality
|
//! managing user sessions. It includes functionality
|
||||||
//! for loading configuration, starting and stopping sessions, and
|
//! for loading configuration, starting and stopping sessions, and
|
||||||
//! handling session-related events.
|
//! handling session-related events.
|
||||||
use crate::configuration::Configuration;
|
use crate::configuration::Configuration;
|
||||||
use crate::{APPLICATION_NAME, VERSION};
|
use crate::{APPLICATION_NAME, VERSION};
|
||||||
use gio::{self, DBusConnection, OwnerId, ResourceLookupFlags};
|
use gio::{self, DBusConnection, OwnerId, RegistrationId};
|
||||||
use glib::{g_debug, g_info, g_warning};
|
use glib::{g_critical, g_debug, g_info, g_warning};
|
||||||
use lazy_static::*;
|
use lazy_static::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
@@ -21,14 +21,22 @@ const G_DBUS_METHOD_LOGIN: &str = "login";
|
|||||||
const G_PROCESSES_MON_TO: u64 = 500; // Interval for monitoring child processes in milliseconds
|
const G_PROCESSES_MON_TO: u64 = 500; // Interval for monitoring child processes in milliseconds
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// static global mutex variable that stores the current state of the session manager process, which can be either Running, End, or Reload.
|
/// A global instance of the `SessionManager` wrapped in a `Mutex` for thread safety.
|
||||||
/// This variable is used to control the behavior of the session manager based on signals received (e.g., SIGHUP for reload, SIGINT/SIGTERM for shutdown).
|
/// This allows the session manager to be accessed and modified from different parts of the application
|
||||||
|
/// while ensuring that only one instance is active at a time.
|
||||||
static ref G_SESSION_MANAGER: Arc<Mutex<SessionManagerState>> = Arc::new(Mutex::<SessionManagerState>::new(SessionManagerState::End));
|
static ref G_SESSION_MANAGER: Arc<Mutex<SessionManagerState>> = Arc::new(Mutex::<SessionManagerState>::new(SessionManagerState::End));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SessionManagerState
|
||||||
|
///
|
||||||
|
/// An enum representing the state of the session manager. It can be in a running state with an active `SessionManager`,
|
||||||
|
/// or it can be in an end or reload state.
|
||||||
pub enum SessionManagerState {
|
pub enum SessionManagerState {
|
||||||
|
/// The session manager is currently running and managing user sessions.
|
||||||
Running(SessionManager),
|
Running(SessionManager),
|
||||||
|
/// The session manager has been stopped and is no longer managing sessions.
|
||||||
End,
|
End,
|
||||||
|
/// The session manager is in the process of reloading its configuration or restarting.
|
||||||
Reload,
|
Reload,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,20 +48,87 @@ pub struct SessionManager {
|
|||||||
config: Configuration,
|
config: Configuration,
|
||||||
/// The main loop for handling session events.
|
/// The main loop for handling session events.
|
||||||
main_loop: glib::MainLoop,
|
main_loop: glib::MainLoop,
|
||||||
// introspection: gio::DBusNodeInfo,
|
/// The D-Bus owner ID for the session manager's D-Bus name.
|
||||||
bus_owner_id: Option<OwnerId>,
|
bus_owner_id: Option<OwnerId>,
|
||||||
|
/// A list of signal handler IDs for any signals the session manager has connected to.
|
||||||
signals: Vec<glib::SourceId>,
|
signals: Vec<glib::SourceId>,
|
||||||
|
/// The D-Bus connection and registration ID for the session manager's D-Bus object.
|
||||||
|
bus_registration: Option<(DBusConnection, RegistrationId)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Public interface for SessionManager
|
||||||
|
///
|
||||||
pub trait SessionManagerInterface {
|
pub trait SessionManagerInterface {
|
||||||
|
/// Run the session manager with an input config file
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&self` - Object that implements the Trait
|
||||||
|
/// - `config` (`&PathBuf`) - Config file.
|
||||||
|
/// - `is_dbus_session` (`bool`) - run the session manager using session DBUS or system DBUS
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - `bool` - if True service shall be restarted after finished
|
||||||
|
///
|
||||||
fn run(&self, config: &PathBuf, is_dbus_session: bool) -> bool;
|
fn run(&self, config: &PathBuf, is_dbus_session: bool) -> bool;
|
||||||
|
|
||||||
|
/// Quit the current session manager service
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&self` - Object that implements the Trait
|
||||||
|
/// - `reload` (`bool`) - if true the service shall be restarted after finished
|
||||||
|
///
|
||||||
fn quit(&self, reload: bool);
|
fn quit(&self, reload: bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait that defines callbacks for SessionManager
|
||||||
|
///
|
||||||
trait SessionManagerCallback {
|
trait SessionManagerCallback {
|
||||||
|
/// Handler for DBUS name acquired event
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&self` - Object that implements the Trait.
|
||||||
|
/// - `connection` (`DBusConnection`) - DBUS connection.
|
||||||
|
/// - `name` (`&str`) - DBUS name.
|
||||||
|
///
|
||||||
fn on_name_acquired(&self, connection: DBusConnection, name: &str);
|
fn on_name_acquired(&self, connection: DBusConnection, name: &str);
|
||||||
|
|
||||||
|
/// Handler for DBUS bus acquired event
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&self` - Object that implements this Trait
|
||||||
|
/// - `connection` (`DBusConnection`) - DBUS connection
|
||||||
|
/// - `name` (`&str`) - DBUS name
|
||||||
|
///
|
||||||
fn on_bus_acquired(&self, connection: DBusConnection, name: &str);
|
fn on_bus_acquired(&self, connection: DBusConnection, name: &str);
|
||||||
|
|
||||||
|
/// Hander for DBUS name lost event
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&self` - Object that implements this Trait
|
||||||
|
/// - `connection` (`Option<DBusConnection>`) - DBUS connection.
|
||||||
|
/// - `name` (`&str`) - DBUS name.
|
||||||
|
///
|
||||||
fn on_name_lost(&self, connection: Option<DBusConnection>, name: &str);
|
fn on_name_lost(&self, connection: Option<DBusConnection>, name: &str);
|
||||||
|
|
||||||
|
/// Handler for DBUS method call event
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&self` (`undefined`) - Object that implements this Trait.
|
||||||
|
/// - `connection` (`DBusConnection`) - DBUS connection.
|
||||||
|
/// - `sender` (`Option<&str>`) - Sender name.
|
||||||
|
/// - `object_path` (`&str`) - DBUS Object path.
|
||||||
|
/// - `interface_name` (`Option<&str>`) - DBUS interface name.
|
||||||
|
/// - `method_name` (`&str`) - DBUS method name.
|
||||||
|
/// - `parameters` (`gio::glib::Variant`) - DBUS method parameters.
|
||||||
|
/// - `invocation` (`gio::DBusMethodInvocation`) - DBUS method invocation object.
|
||||||
|
///
|
||||||
fn on_method_call(
|
fn on_method_call(
|
||||||
&self,
|
&self,
|
||||||
connection: DBusConnection,
|
connection: DBusConnection,
|
||||||
@@ -64,7 +139,14 @@ trait SessionManagerCallback {
|
|||||||
parameters: gio::glib::Variant,
|
parameters: gio::glib::Variant,
|
||||||
invocation: gio::DBusMethodInvocation,
|
invocation: gio::DBusMethodInvocation,
|
||||||
);
|
);
|
||||||
fn on_process_monitor(&self);
|
|
||||||
|
/// Hander for service processes monitor
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&self` - Object that implements this Trait
|
||||||
|
///
|
||||||
|
fn on_processes_monitor(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionManagerInterface for Arc<Mutex<SessionManagerState>> {
|
impl SessionManagerInterface for Arc<Mutex<SessionManagerState>> {
|
||||||
@@ -75,6 +157,7 @@ impl SessionManagerInterface for Arc<Mutex<SessionManagerState>> {
|
|||||||
main_loop: glib::MainLoop::new(None, false),
|
main_loop: glib::MainLoop::new(None, false),
|
||||||
bus_owner_id: None,
|
bus_owner_id: None,
|
||||||
signals: Vec::new(),
|
signals: Vec::new(),
|
||||||
|
bus_registration: None,
|
||||||
});
|
});
|
||||||
let evtloop = match self.lock().as_deref_mut().unwrap() {
|
let evtloop = match self.lock().as_deref_mut().unwrap() {
|
||||||
SessionManagerState::Running(session) => {
|
SessionManagerState::Running(session) => {
|
||||||
@@ -84,10 +167,9 @@ impl SessionManagerInterface for Arc<Mutex<SessionManagerState>> {
|
|||||||
_ => panic!("No SessionManager created"),
|
_ => panic!("No SessionManager created"),
|
||||||
};
|
};
|
||||||
evtloop.run();
|
evtloop.run();
|
||||||
if let SessionManagerState::Reload = self.lock().as_deref().unwrap() {
|
match self.lock().as_deref().unwrap() {
|
||||||
true
|
SessionManagerState::Reload => true,
|
||||||
} else {
|
_ => false,
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,9 +192,21 @@ impl SessionManagerCallback for Arc<Mutex<SessionManagerState>> {
|
|||||||
|
|
||||||
fn on_bus_acquired(&self, connection: DBusConnection, name: &str) {
|
fn on_bus_acquired(&self, connection: DBusConnection, name: &str) {
|
||||||
g_debug!(APPLICATION_NAME, "D-BUS acquired for name {}", name);
|
g_debug!(APPLICATION_NAME, "D-BUS acquired for name {}", name);
|
||||||
let introspection = gio::DBusNodeInfo::for_xml(G_DBUS_INTROSPECTION).unwrap();
|
let introspection = match gio::DBusNodeInfo::for_xml(G_DBUS_INTROSPECTION) {
|
||||||
|
Ok(info) => info,
|
||||||
|
Err(err) => {
|
||||||
|
g_critical!(
|
||||||
|
APPLICATION_NAME,
|
||||||
|
"Failed to parse D-Bus introspection data: {}",
|
||||||
|
err
|
||||||
|
);
|
||||||
|
self.quit(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
let interface = &introspection.interfaces()[0];
|
let interface = &introspection.interfaces()[0];
|
||||||
let _ = connection
|
|
||||||
|
let registration_id = match connection
|
||||||
.register_object(G_DBUS_SERVER_PATH, interface)
|
.register_object(G_DBUS_SERVER_PATH, interface)
|
||||||
.method_call(
|
.method_call(
|
||||||
|connection: DBusConnection,
|
|connection: DBusConnection,
|
||||||
@@ -134,11 +228,25 @@ impl SessionManagerCallback for Arc<Mutex<SessionManagerState>> {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
.expect("Failed to register D-Bus object");
|
{
|
||||||
|
Err(error) => {
|
||||||
|
g_critical!(
|
||||||
|
APPLICATION_NAME,
|
||||||
|
"Failed to register D-Bus object at path {}: {}",
|
||||||
|
G_DBUS_SERVER_PATH,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
self.quit(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ok(resource) => resource,
|
||||||
|
};
|
||||||
|
if let SessionManagerState::Running(session) = self.lock().as_deref_mut().unwrap() {
|
||||||
|
session.bus_registration = Some((connection, registration_id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_name_lost(&self, _connection: Option<DBusConnection>, name: &str) {
|
fn on_name_lost(&self, _connection: Option<DBusConnection>, name: &str) {
|
||||||
g_warning!(APPLICATION_NAME, "D-Bus name lost: {}", name);
|
g_critical!(APPLICATION_NAME, "D-Bus name lost: {}", name);
|
||||||
if let SessionManagerState::Running(session) = self.lock().as_deref_mut().unwrap() {
|
if let SessionManagerState::Running(session) = self.lock().as_deref_mut().unwrap() {
|
||||||
session.bus_owner_id = None;
|
session.bus_owner_id = None;
|
||||||
}
|
}
|
||||||
@@ -147,9 +255,9 @@ impl SessionManagerCallback for Arc<Mutex<SessionManagerState>> {
|
|||||||
|
|
||||||
fn on_method_call(
|
fn on_method_call(
|
||||||
&self,
|
&self,
|
||||||
connection: DBusConnection,
|
_connection: DBusConnection,
|
||||||
sender: Option<&str>,
|
_sender: Option<&str>,
|
||||||
object_path: &str,
|
_object_path: &str,
|
||||||
interface_name: Option<&str>,
|
interface_name: Option<&str>,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
parameters: gio::glib::Variant,
|
parameters: gio::glib::Variant,
|
||||||
@@ -183,17 +291,38 @@ impl SessionManagerCallback for Arc<Mutex<SessionManagerState>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_process_monitor(&self) {}
|
fn on_processes_monitor(&self) {
|
||||||
|
if let SessionManagerState::Running(session) = self.lock().as_deref_mut().unwrap() {
|
||||||
|
session.monitor();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionManager {
|
impl SessionManager {
|
||||||
|
/// Get a threadsafe singleton instance of the SessionManager
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - `Arc<Mutex<SessionManagerState>>` - Smart pointer to SessionManager
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use dysm_rs::SessionManager;
|
||||||
|
///
|
||||||
|
/// let instance = SessionManager::instance();
|
||||||
|
/// ```
|
||||||
pub fn instance() -> Arc<Mutex<SessionManagerState>> {
|
pub fn instance() -> Arc<Mutex<SessionManagerState>> {
|
||||||
G_SESSION_MANAGER.clone()
|
G_SESSION_MANAGER.clone()
|
||||||
}
|
}
|
||||||
/// Set up the session manager.
|
|
||||||
|
/// Setup the session manager before running
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&mut self` (`&mut SessionManager`) - Mutable reference to SessionManager.
|
||||||
|
/// - `is_dbus_session` (`bool`) - if true setup service using DBUS session, otherwise SBUS system
|
||||||
///
|
///
|
||||||
/// This method starts the main loop and begins handling session events.
|
|
||||||
/// It will block until the main loop is quit, at which point it will return.
|
|
||||||
fn setup(&mut self, is_dbus_session: bool) {
|
fn setup(&mut self, is_dbus_session: bool) {
|
||||||
g_info!(
|
g_info!(
|
||||||
APPLICATION_NAME,
|
APPLICATION_NAME,
|
||||||
@@ -245,17 +374,37 @@ impl SessionManager {
|
|||||||
// Monitor child processes here
|
// Monitor child processes here
|
||||||
// For example, you could check if any child processes have exited and handle that accordingly
|
// For example, you could check if any child processes have exited and handle that accordingly
|
||||||
// g_debug!(APPLICATION_NAME, "Monitoring child processes...");
|
// g_debug!(APPLICATION_NAME, "Monitoring child processes...");
|
||||||
SessionManager::instance().on_process_monitor();
|
SessionManager::instance().on_processes_monitor();
|
||||||
glib::ControlFlow::Continue
|
glib::ControlFlow::Continue
|
||||||
});
|
});
|
||||||
self.signals.push(processes_monitor_id);
|
self.signals.push(processes_monitor_id);
|
||||||
// Implementation for running the session manager
|
// Implementation for running the session manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Process DBUS login method cal
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&self` (`&mut SessionManager`) - Mutable reference to current SessionManager.
|
||||||
|
/// - `parameters` (`&gio::glib::Variant`) - DBUS method parameters.
|
||||||
|
/// - `invocation` (`gio::DBusMethodInvocation`) - DBUS method invocation object.
|
||||||
|
///
|
||||||
fn login(&self, parameters: &gio::glib::Variant, invocation: gio::DBusMethodInvocation) {
|
fn login(&self, parameters: &gio::glib::Variant, invocation: gio::DBusMethodInvocation) {
|
||||||
g_debug!(APPLICATION_NAME, "Logging called");
|
g_debug!(APPLICATION_NAME, "Logging called");
|
||||||
invocation.return_dbus_error(G_DBUS_SERVER_ERROR_NAME, "Unimplemented");
|
invocation.return_dbus_error(G_DBUS_SERVER_ERROR_NAME, "Unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Monitor session processes
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `&self` (`&mut SessionManager`) - Mutable reference to current SessionManager.
|
||||||
|
///
|
||||||
|
fn monitor(&self) {
|
||||||
|
// Here you would implement the logic to monitor child processes.
|
||||||
|
// For example, you could check if any child processes have exited and handle that accordingly.
|
||||||
|
g_debug!(APPLICATION_NAME, "Monitoring child processes...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for SessionManager {
|
impl Drop for SessionManager {
|
||||||
@@ -265,6 +414,19 @@ impl Drop for SessionManager {
|
|||||||
g_debug!(APPLICATION_NAME, "Releasing acquired D-Bus name");
|
g_debug!(APPLICATION_NAME, "Releasing acquired D-Bus name");
|
||||||
gio::bus_unown_name(bus_owner_id);
|
gio::bus_unown_name(bus_owner_id);
|
||||||
}
|
}
|
||||||
|
if let Some((connection, registration_id)) = self.bus_registration.take() {
|
||||||
|
g_debug!(APPLICATION_NAME, "Unregistering D-Bus object");
|
||||||
|
connection
|
||||||
|
.unregister_object(registration_id)
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
g_critical!(
|
||||||
|
APPLICATION_NAME,
|
||||||
|
"Unable to unregister object from D-Bus connection: {}",
|
||||||
|
e
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
g_debug!(APPLICATION_NAME, "Removing signal handlers");
|
||||||
for signal_id in self.signals.drain(..) {
|
for signal_id in self.signals.drain(..) {
|
||||||
signal_id.remove();
|
signal_id.remove();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user