1. Overview
The RootGuardClient.hpp header defines the asynchronous GTK-facing client API used by the RootGuard page. It packages service state, recent security events, application-rule state, and operation feedback into snapshots while hiding privileged command execution and worker-thread details behind a compact signal-based interface.
The file integrates the following components, APIs, or runtime concepts:
- RootGuardEvent.hpp – typed representation of RootGuard JSON events
- Glib::Dispatcher – transfers completed worker results back to the GTK main thread
- sigc++ – exposes the snapshot update signal
- std::thread / mutex / condition_variable – serialize asynchronous service and incident actions
2. Data Models
ServiceStatus records whether the daemon is active, whether immediate protection is effectively enabled, whether automatic service blocking and user-home blocking are enabled, and the detected init system, runtime state, policy mode, metadata actions, and daemon PID.
ApplicationRules contains three editable lists: routine trusted applications, privilege-trusted executables, and denied executables.
Snapshot is the value delivered to the UI. It combines service status, parsed events, application rules, the most recent operation message, and an operation-success flag.
3. Public Client API
refresh()– collect current service status, recent events, and rule statestart_service(),stop_service(),reload_policy(),restart_service()– enqueue daemon lifecycle actionsset_immediate_protection(bool)– request audit/enforcement policy switchingrestore_event()andremove_event()– request incident recovery or quarantinesave_application_rules()– persist the three application-rule listssignal_updated()– notify GTK consumers after a worker operation completes
4. Request Queue and Action Model
The private Action enumeration covers refresh, lifecycle operations, protection switching, restore, removal, rule saving, and thread shutdown. Each queued Request can carry a boolean state, an optional Event, or a complete ApplicationRules value.
Copy construction and assignment are disabled because the class owns synchronization primitives, a dispatcher, a request queue, and a worker thread.
5. Threading Contract
enqueue() places requests behind a mutex and wakes the worker. worker_loop() executes the request outside the GTK thread, builds a new Snapshot, stores it as the pending result, and emits the Glib::Dispatcher.
on_dispatch() runs on the GTK side, moves the pending snapshot out under the mutex, and emits the sigc++ update signal. This keeps blocking process execution and file parsing away from UI callbacks.
6. Runtime and Security Considerations
- Single worker ownership: operations are serialized instead of running competing privileged commands concurrently.
- Main-thread handoff: GTK consumers receive results through
Glib::Dispatcherrather than direct worker-thread widget access. - Orderly teardown: destruction clears queued work, pushes a
Quitrequest, signals the condition variable, and joins the thread.
