-
-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Erroneous type deserialization on some signals #21
Comments
Would you please share some parts of your code, so I can try to reproduce this issue myself? |
…pty object path array signature and unit test that reproduces the incorrect parsing
Please see the commited unit test in my fork, if you debug it and change the offset array input for second |
I also want to try it against connman. |
When I am monitoring Connman DBus traffic with
(seems legit?) At approximately same time I hit a breakpoint that deserializes the parameters to
The handler (inner class):
Signal (inner class), this is being constructed when getting the CCE:
|
This is really a tough one. I'll take a deeper look into it. Maybe the whole parsing stuff should be re-designed. |
So I think I got the solution. After digging around in the Message and Marshalling class, I think there is nothing wrong. The mistake in my view is in your PathProperties class (the part of your code, you did not publish). The provided unit test fails, because using If you need custom classes like in this case (a holder which extends I updated the unit test to do so and also implemented a proper 'Struct', so unit test is now fine. For completeness, here is my test code I used to talk to connman: import java.util.List;
import java.util.Map;
import org.freedesktop.dbus.DBusPath;
import org.freedesktop.dbus.ObjectPath;
import org.freedesktop.dbus.Struct;
import org.freedesktop.dbus.annotations.DBusInterfaceName;
import org.freedesktop.dbus.annotations.Position;
import org.freedesktop.dbus.connections.impl.DBusConnection;
import org.freedesktop.dbus.connections.impl.DBusConnection.DBusBusType;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.handlers.AbstractSignalHandlerBase;
import org.freedesktop.dbus.interfaces.DBusInterface;
import org.freedesktop.dbus.messages.DBusSignal;
import org.freedesktop.dbus.types.Variant;
public class TestConnman {
public static void main(String[] args) throws DBusException, InterruptedException {
DBusConnection connection = DBusConnection.getConnection(DBusBusType.SYSTEM);
connection.addSigHandler(IServicesChanged.ServicesChanged.class, new ServiceChangedHandler() {
@Override
public void handle(IServicesChanged.ServicesChanged _signal) {
System.out.print("Received signal.");
System.out.println("Removed devices: " + _signal.getRemoved());
System.out.println("Changed properties: " + someDataToString(_signal.getChanged()));
}
private String someDataToString(List<SomeData> changed) {
StringBuilder sb = new StringBuilder();
for (SomeData string : changed) {
sb.append("DbusPath: ").append(string.getObjectPath()).append(" - Properties: ")
.append(string.getProperties()).append("\n");
}
return sb.toString();
}
});
Thread.sleep(100000);
}
public abstract static class ServiceChangedHandler
extends AbstractSignalHandlerBase<IServicesChanged.ServicesChanged> {
@Override
public Class<IServicesChanged.ServicesChanged> getImplementationClass() {
return IServicesChanged.ServicesChanged.class;
}
}
@DBusInterfaceName("net.connman.Manager")
interface IServicesChanged extends DBusInterface {
public static class ServicesChanged extends DBusSignal {
public final String objectPath;
public final List<SomeData> changed;
public final List<ObjectPath> removed;
public ServicesChanged(String _objectPath, List<SomeData> _k, List<ObjectPath> _removedItems)
throws DBusException {
super(_objectPath, _k, _removedItems);
objectPath = _objectPath;
changed = _k;
removed = _removedItems;
}
public String getObjectPath() {
return objectPath;
}
public List<SomeData> getChanged() {
return changed;
}
public List<ObjectPath> getRemoved() {
return removed;
}
}
}
public static class SomeData extends Struct {
@Position(0)
public DBusPath objectPath;
@Position(1)
public Map<String, Variant<?>> properties;
public SomeData(DBusPath objectPath, Map<String, Variant<?>> properties) {
this.objectPath = objectPath;
this.properties = properties;
}
DBusPath getObjectPath() {
return objectPath;
}
void setObjectPath(DBusPath _objectPath) {
objectPath = _objectPath;
}
Map<String, Variant<?>> getProperties() {
return properties;
}
void setProperties(Map<String, Variant<?>> _properties) {
properties = _properties;
}
}
}
|
I had the exact same problem. The issue seems to be that, if the changedServices list is empty, the optimizePrimitives method in the Message class wants to skip the signature of the struct (Message:1054). The length of the struct signature is calculated by using Marshalling.getJavaType, which returns a size that is one off for structs if I read it correctly. See my small fix above. |
I am listening to some signals from DBus, one of them is "ServicesChanged" from Connman, which has a signature of
a(oa{sv})ao
.It seems that the signals that have the first array as empty, and the other array (of object paths) non-empty, result in a
ClassCastException
:What seems to happen is that while getting the signal constructor parameters in
Message.getParameters()
, the array of object paths is interpreted as one object path (the one path value is all the object path strings mangled together plus some garbage inbetween). Then when giving the parameters to Reflection, an exception is thrown as the wrongly deserialized constructor param isObjectPath
and notList<ObjectPath>
.Specifically, after having parsed the empty first array, the second round of
extractOne
method for the non-empty object path array is given an offset array which seems to have its first element (signature offset) one element too far and this makes the method try to parse an array of object paths as one. Hence the first round ofextractOne
of the two seems to update the offset to a value one too many. When I debug and set the signature offset to a value one less forextractOne
after extracting the empty array, the parameters are deserialized correctly.This is happening in (little-endian) signals with this exact signature, in 2.7.* and 3.0 both.
The text was updated successfully, but these errors were encountered: