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

Not support put operation in DBusMap #169

Closed OOOleo closed 2 years ago

OOOleo commented 2 years ago

Hi, recently, when using dbus to change the IP, it is necessary to obtain the connection information of the network card, then modify the ipv4 attribute inside, and then update the configuration, but when modifying the attribute, DBusMap does not support the put operation. I guess that for some security reasons or other reasons, the modification operation of DBusMap is not supported, but this will indeed cause a lot of trouble to this modification operation, which is not very convenient. Here I allow the put operation by modifying your source code, and then I can modify the IP smoothly. I would like to know if this is the correct way, and if DBusMap can support put operations. Thanks.

hypfvieh commented 2 years ago

Please provide a test case for this.

OOOleo commented 2 years ago
public static void changeIPTest() {
        String path = "/org/freedesktop/NetworkManager/Settings/1";
        try (DBusConnection dbusConn = DBusConnectionBuilder.forSystemBus().withShared(false).build()) {
                Connection sConnection= dbusConn.getRemoteObject("org.freedesktop.NetworkManager",path,
                        Connection.class);
                Map<String, Map<String, Variant<?>>> sMap = sConnection.GetSettings();
                String ip = "192.168.142.238";
                String gateway = "192.168.142.2";
                Map<String, Variant<?>> ipv4Map = sMap.get("ipv4");
                List<Map<String, Variant<?>>> addressData = new ArrayList<>();
                Map<String, Variant<?>> addressDataElement = new HashMap<>();
                addressDataElement.put("address", new Variant<>(ip));
                addressDataElement.put("prefix", new Variant<>(24));
                addressData.add(addressDataElement);
                List<UInt32> address = new ArrayList<>();
                List<List<UInt32>> addresses = new ArrayList<>();
                address.add(new UInt32(NetUtil.ipv4ToLong(NMUtil.reverseIP(ip))));
                address.add(new UInt32(24));
                address.add(new UInt32(NetUtil.ipv4ToLong(NMUtil.reverseIP(gateway))));
                addresses.add(address);
                ipv4Map.put("address-data", new Variant<>(addressData,"aa{sv}"));
                ipv4Map.put("addresses", new Variant<>(addresses,"aau"));
                ipv4Map.put("method", new Variant<>("manual"));
                ipv4Map.put("gateway", new Variant<>(gateway));
                sConnection.Update(sMap);
                //Active Connection

            } catch (DBusException | IOException ex) {
            ex.printStackTrace();
        }
    }
hypfvieh commented 2 years ago

You get DBusMap instance here because the map should not be modifiable in any way (no put, no remove). This is intended to prevent you from changing the map content and expect the changed values will be "magically" send back using DBus.

If you need to modify the map, you have to copy the contents to a HashMap (or similiar) using new HashMap<>(receivedDBusMap), make your changes and use this to call Update(Map).

OOOleo commented 2 years ago

This is indeed a better solution and it works. I fell into a misunderstanding, thinking that the Map type parameter of DBus must be DBusMap... Thanks for you help