hypfvieh / dbus-java

Improved version of java DBus library provided by freedesktop.org (https://dbus.freedesktop.org/doc/dbus-java/)
https://hypfvieh.github.io/dbus-java/
MIT License
185 stars 73 forks source link

How can I make a system call? #136

Closed snowsky closed 3 years ago

snowsky commented 3 years ago

Hi there, I'm trying to send a message to the system interface, for example, "org.freedesktop.login1.Manager.Reboot" to reboot the box. It is seen that there are 3 messages sent and it hangs at the message/signal NameAcquired. I am trying to understand why there are 3 messages sent and how I can send thru the last message. Please let me know if this is a known issue. Thanks.

[main] DEBUG org.freedesktop.dbus.connections.transports.TransportFactory - Connecting to UNIX: {path=/var/run/dbus/system_bus_socket} [main] DEBUG org.freedesktop.dbus.connections.transports.UnixSocketTransport - No alternative ISocketProvider found, using built-in implementation. inputReader = null, outputWriter = null [main] DEBUG org.freedesktop.dbus.messages.MethodCall - Creating message with serial 1 [main] DEBUG org.freedesktop.dbus.messages.MethodCall - Appending sig: yyyy data: [108, 1, 0, 1] [main] DEBUG org.freedesktop.dbus.messages.MethodCall - Appending sig: ua(yv) data: [1, [[1, [o, /org/freedesktop/DBus]], [6, [s, org.freedesktop.DBus]], [2, [s, org.freedesktop.DBus]], [3, [s, Hello]]]] [main] DEBUG org.freedesktop.dbus.messages.MethodCall - Appended body, type: null start: 128 end: 128 size: 0 [main] DEBUG org.freedesktop.dbus.messages.MethodCall - marshalled size ([0, 0, 0, 0]): 000000 00 00 00 00 .... [DBus Sender Thread-1] DEBUG org.freedesktop.dbus.spi.OutputStreamMessageWriter - <= MethodCall(0,1) { Path=>/org/freedesktop/DBus, Interface=>org.freedesktop.DBus, Member=>Hello, Destination=>org.freedesktop.DBus } { } [DBusConnection] DEBUG org.freedesktop.dbus.spi.InputStreamMessageReader - => MethodReturn(1,1) { Reply Serial=>1, Destination=>:1.92, Sender=>org.freedesktop.DBus, Signature=>s } { :1.92 } [DBusConnection] DEBUG org.freedesktop.dbus.connections.impl.DBusConnection - Handling incoming method return: MethodReturn(1,1) { Reply Serial=>1, Destination=>:1.92, Sender=>org.freedesktop.DBus, Signature=>s } { :1.92 } [main] DEBUG org.freedesktop.dbus.messages.DBusSignal - Creating message with serial 2 [main] DEBUG org.freedesktop.dbus.messages.DBusSignal - Appending sig: yyyy data: [108, 4, 0, 1] [main] DEBUG org.freedesktop.dbus.messages.DBusSignal - Appending sig: ua(yv) data: [3, [[1, [o, /org/freedesktop/login1]], [2, [s, org.freedesktop.login1.Manager]], [3, [s, CanReboot]]]] [DBusConnection] DEBUG org.freedesktop.dbus.spi.InputStreamMessageReader - => DBusSignal [clazz=null] [DBusConnection] DEBUG org.freedesktop.dbus.connections.impl.DBusConnection - Handling incoming signal: DBusSignal [clazz=null] [DBus Sender Thread-1] DEBUG org.freedesktop.dbus.spi.OutputStreamMessageWriter - <= DBusSignal [clazz=null] [DBus Worker Thread-1] DEBUG org.freedesktop.dbus.messages.DBusSignal - Converting signal to type: class org.freedesktop.DBus$NameAcquired [DBus Worker Thread-1] DEBUG org.freedesktop.DBus$NameAcquired - Creating message with serial 3 [DBus Worker Thread-1] DEBUG org.freedesktop.DBus$NameAcquired - Appending sig: yyyy data: [108, 4, 0, 1] [DBus Worker Thread-1] DEBUG org.freedesktop.DBus$NameAcquired - Appending sig: ua(yv) data: [4, [[1, [o, /org/freedesktop/DBus]], [2, [s, org.freedesktop.DBus]], [3, [s, NameAcquired]], [8, [g, s]]]]

hypfvieh commented 3 years ago

Sample code to demonstrate the issue will also be helpful. Without knowning what you are doing in your code it is hard to see if something is wrong.

3 messages are send, because every application which uses DBus must first register at DBus doing some sort of handshake (that's why you see the 'Hello' message). This server will answer to this message and then will do whatever it is supposed to do.

snowsky commented 3 years ago

@hypfvieh Thanks for the reply, my codes is quite simple which is to send a signal to logind interface as below:

    try {
        DBusConnection conn = DBusConnection.getConnection(DBusConnection.DBusBusType.SYSTEM);
        DBusSignal signalToSend = new DBusSignal(null, "/", "org.freedesktop.login1.Manager", "Reboot", null, 1);
        conn.sendMessage(signalToSend);
    } catch (DBusException e) {
        e.printStackTrace();
    }

"Reboot" signal got a boolean argument. I am not sure if I used it correctly. I also tried other signals like "CanReboot" which got no argument but it hangs at the same message, NameAcquired.

Thanks,

hypfvieh commented 3 years ago

grafik

This is not the way to do it.

The LoginManager does not expect signals for the operations you mentioned (see: documention of systemd-logind) or use d-feet to look through the possible methods/signals/properties of an exported DBus object.

Reboot and canReboot are methods in the Manager object (org.freedesktop.login1.Manager), so you first have to create the Java interface for this and then you can gather a instance of org.freedesktop.login1.Manager from DBus. On this object you can call canReboot and Reboot. For creation of the interface you may try to use org.freedesktop.dbus.utils.generator.InterfaceCodeGeneratorwhich is part of dbus-java-utils.

The resulting code would look like this: ` try (DBusConnection sysConn = DBusConnection.getConnection(DBusBusType.SYSTEM)) { Manager mgr = sysConn.getRemoteObject("org.freedesktop.login1", "/org/freedesktop/login1", org.freedesktop.login1.Manager.class);

        System.out.println("Reboot allowed: " + mgr.CanReboot());
        System.out.println("PowerOff allowed: " + mgr.CanPowerOff());
    }
}`

The results should be 'yes' and 'yes' if it is allows to reboot/poweroff the device. The result type of the CanXXX methods are String (not boolean), and will return 'yes' or 'no' (again see documention).

I also added sample code to my sandbox repository for this case, see here and here.

snowsky commented 3 years ago

Thanks @hypfvieh for the details, really appreciate that. Let me close the issue 👍

snowsky commented 3 years ago

@hypfvieh, I got some errors while using the version 3.2.4. I guess you may need to deploy a new version 3.3.0 to maven repo. :)

hypfvieh commented 3 years ago

If you want to use my generated sources, you have to use 3.3.0 of dbus-java because it contains some new types and annotations. If you create the interface files yourself using dbus-java-utils 3.2.4 it will also work with the older version.

snowsky commented 3 years ago

Thanks, what will be the release plan for version 3.3.0? I looked around in the repo but didn't find an example to use dbus-java-utils for the interface. I copied your java files and it worked. I believe there must be a simple way to define the interface lol

hypfvieh commented 3 years ago

easiest way to execute the generator is to checkout the sources of 3.2.4 and use maven to run the util. Building the commandline manually is pretty ugly due to the many dependencies... See also: https://hypfvieh.github.io/dbus-java/code-generation.html