2024-09-19 10:45:52 +00:00
pub mod formats {
pub mod json ;
2024-09-20 06:42:41 +00:00
pub mod plain ;
2024-09-22 10:18:27 +00:00
pub mod rson ;
2024-09-23 14:57:43 +00:00
pub mod serde ;
2024-09-19 10:45:52 +00:00
}
2024-09-16 20:51:27 +00:00
mod notification ;
2024-09-19 10:45:52 +00:00
use notification ::{ to_notif , Notification } ;
2024-09-18 19:44:46 +00:00
use std ::collections ::HashMap ;
2024-09-26 08:07:39 +00:00
pub mod optparse ;
2024-09-16 11:19:08 +00:00
2024-09-16 20:51:27 +00:00
use futures_util ::stream ::TryStreamExt ;
2024-09-19 10:45:52 +00:00
use zbus ::{ message ::Body , Connection , Result } ;
2024-08-27 11:28:05 +00:00
2024-09-17 18:32:16 +00:00
const SERVER_NAME : & str = " SNot " ; // Server software name
2024-09-18 18:22:45 +00:00
const VENDOR : & str = " candifloss.cc " ; // Server software vendor
2024-09-23 14:57:43 +00:00
const VERSION : & str = " 0.1.2 " ; // Server software version
2024-09-18 18:22:45 +00:00
const SPEC_VERSION : & str = " 0.42 " ; // DBus specification version
2024-09-19 10:45:52 +00:00
const NOTIF_INTERFACE : & str = " org.freedesktop.Notifications " ; // DBus interface name
2024-09-18 19:44:46 +00:00
// Properties of this server
fn server_properties ( ) -> HashMap < String , String > {
let mut properties : HashMap < String , String > = HashMap ::new ( ) ;
properties . insert ( " ServerName " . to_string ( ) , String ::from ( SERVER_NAME ) ) ;
properties . insert ( " Vendor " . to_string ( ) , String ::from ( VENDOR ) ) ;
properties . insert ( " Version " . to_string ( ) , String ::from ( VERSION ) ) ;
properties . insert ( " SpecVersion " . to_string ( ) , String ::from ( SPEC_VERSION ) ) ;
properties
}
2024-09-16 21:28:58 +00:00
2024-08-27 11:28:05 +00:00
#[ tokio::main ]
async fn main ( ) -> Result < ( ) > {
2024-09-26 19:21:37 +00:00
// Options
2024-09-26 08:07:39 +00:00
let args : optparse ::Cli = argh ::from_env ( ) ;
2024-09-26 19:21:37 +00:00
// Format: r|j|p
2024-09-26 08:07:39 +00:00
let op_format = match args . format {
2024-09-26 19:21:37 +00:00
Some ( value ) = > {
// Reject invalid format option
if [ " r " , " j " , " p " ] . contains ( & value . as_str ( ) ) {
value . clone ( )
} else {
// Exit with error code
return Err ( zbus ::Error ::from ( std ::io ::Error ::new (
std ::io ::ErrorKind ::InvalidInput ,
" Invalid output format " ,
) ) ) ;
}
}
2024-09-26 10:46:46 +00:00
None = > " j " . to_string ( ) ,
2024-09-22 05:46:51 +00:00
} ;
2024-09-26 19:21:37 +00:00
// Verbose mode. Off/false by default
2024-09-26 10:46:46 +00:00
let verbose = args . verbose ;
2024-09-22 10:18:27 +00:00
2024-08-27 11:28:05 +00:00
let connection = Connection ::session ( ) . await ? ;
2024-09-01 08:20:17 +00:00
connection
2024-09-18 19:44:46 +00:00
. request_name ( NOTIF_INTERFACE ) // Requesting dbus for this service name. Any other services/procs using this name should be stopped/disabled before this
2024-09-01 08:20:17 +00:00
. await ? ;
2024-08-25 21:10:15 +00:00
2024-09-15 15:43:09 +00:00
let mut stream = zbus ::MessageStream ::from ( & connection ) ; // Convert connection to a MessageStream, yields Message items
2024-09-01 11:31:19 +00:00
2024-09-22 05:46:51 +00:00
// Notification id, restarts with each session
let mut notification_id : u32 = 0 ;
2024-09-18 18:22:45 +00:00
// Iterate on the message stream
2024-09-01 11:31:19 +00:00
while let Some ( msg ) = stream . try_next ( ) . await ? {
2024-09-18 18:22:45 +00:00
// Check the method calls in the received message's header
2024-09-16 20:51:27 +00:00
if let Some ( member ) = msg . header ( ) . member ( ) {
2024-09-18 18:22:45 +00:00
let member_name = member . as_str ( ) ; // Convert to &str for the match
2024-09-16 20:51:27 +00:00
match member_name {
2024-09-18 19:44:46 +00:00
" GetAll " = > {
// Client requested all properties of the server. Extract the interface name from the message body
let interface_name : String = msg . body ( ) . deserialize ( ) ? ; // This method has only one parameter, the interface name
2024-09-19 10:45:52 +00:00
// Check if the requested interface is the right one
2024-09-18 19:44:46 +00:00
if interface_name = = NOTIF_INTERFACE {
// Properties for the interface
let properties = server_properties ( ) ;
// Reply with the properties
connection . reply ( & msg , & properties ) . await ? ;
2024-09-22 10:18:27 +00:00
if verbose {
println! ( " GetAll request received for interface: {interface_name} " ) ;
}
2024-09-18 19:44:46 +00:00
} else {
2024-09-18 22:34:25 +00:00
// Reply with an error
connection
. reply_error (
& msg ,
" org.freedesktop.DBus.Error.UnknownInterface " ,
& " Unknown interface " . to_string ( ) ,
)
. await ? ;
2024-09-26 10:46:46 +00:00
if verbose {
println! ( " Unknown interface requested: {interface_name} " ) ;
}
2024-09-18 19:44:46 +00:00
}
}
2024-09-15 18:10:19 +00:00
" GetServerInformation " = > {
2024-09-18 18:22:45 +00:00
// Client requested server information. Respond with: (Server_name, author, software_version, dbus_spec_version)
2024-09-18 11:23:39 +00:00
let response = ( SERVER_NAME , VENDOR , VERSION , SPEC_VERSION ) ;
2024-09-15 18:10:19 +00:00
connection . reply ( & msg , & response ) . await ? ;
2024-09-22 10:18:27 +00:00
if verbose {
println! ( " Request received: {member} \n \t Name: {SERVER_NAME} , Vendor: {VENDOR} , Version: {VERSION} , DBus spec version: {SPEC_VERSION} " ) ;
// Remove this LATER
}
2024-09-15 18:10:19 +00:00
}
2024-09-16 20:51:27 +00:00
" GetCapabilities " = > {
2024-09-18 18:22:45 +00:00
// Client requested server capabilities. Respond with the supported capabilities
let capabilities = vec! [ " actions " , " body " , " body-hyperlinks " ] ; // Add more LATER
2024-09-20 06:42:41 +00:00
connection . reply ( & msg , & capabilities ) . await ? ;
2024-09-22 10:18:27 +00:00
if verbose {
println! ( " Request received: {member} \n \t Capabilities: {capabilities:?} " ) ;
// Remove this LATER
}
2024-09-16 20:51:27 +00:00
}
2024-09-15 18:10:19 +00:00
" Notify " = > {
2024-09-18 18:22:45 +00:00
// New notification received. Now, respond to the client with a notification ID
2024-09-22 05:46:51 +00:00
notification_id + = 1 ; // This could be incremented or generated.
2024-09-18 18:22:45 +00:00
connection . reply ( & msg , & notification_id ) . await ? ; // The client waits for this response in order to disconnect
2024-09-19 10:45:52 +00:00
// Get the body of the message
let msg_body : Body = msg . body ( ) ; // The body has 8 parameters, ie., 8 fields of a Notification object
// Convert the msg body to a Notification object
let notif : Notification = to_notif ( & msg_body ) ? ;
2024-09-18 18:22:45 +00:00
// Handle the notif
2024-09-26 08:07:39 +00:00
match op_format . as_str ( ) {
2024-09-22 10:18:27 +00:00
" j " = > {
println! ( " {} " , & notif . json ( ) ) ; // Print the json version
}
" r " = > {
2024-09-26 08:07:39 +00:00
println! ( " {} " , & notif . rson ( ) ) ; // Print the rson version
2024-09-22 10:18:27 +00:00
}
" p " = > {
println! ( " {} \n " , & notif . plain ( ) ) ; // Print the plain version
}
_ = > {
2024-09-26 19:21:37 +00:00
println! ( " Onkown output format. " ) ; // This is probably unreachable
2024-09-22 10:18:27 +00:00
}
2024-09-22 05:46:51 +00:00
}
2024-09-18 18:22:45 +00:00
}
" CloseNotification " = > {
2024-09-26 19:21:37 +00:00
// Client sent a 'close' signal. Extract notification ID of the notif to be closed from the message body
2024-09-18 22:34:25 +00:00
let notification_id : u32 = msg . body ( ) . deserialize ( ) ? ; // This method has only one parameter, the id
2024-09-18 18:22:45 +00:00
// Tracking notifications by their IDs, closing them, and other features may be implemented later
// close_notification(notification_id);
2024-09-22 10:18:27 +00:00
if verbose {
println! ( " Closing notification with ID: {notification_id} " ) ;
}
2024-09-18 18:22:45 +00:00
// Respond to the client, acknowledging the closure
connection . reply ( & msg , & ( ) ) . await ? ;
2024-09-15 18:10:19 +00:00
}
_ = > {
2024-09-22 10:18:27 +00:00
if verbose {
println! ( " Unhandled method: {member} " ) ; // Other methods are either irrelevant or unhandled at this stage of development
}
2024-09-15 18:10:19 +00:00
}
2024-09-16 20:51:27 +00:00
}
2024-09-14 10:33:40 +00:00
}
2024-09-01 11:31:19 +00:00
}
Ok ( ( ) )
}