cgdbusconnman

What is the right way to register RequestInput function to ConnMan?


I'm implementing C application which should be capable of connecting to external Wi-Fi protected access points using ConnMan via GDbus. So far I dig up that the Agent must be registered with RequestInput callback on "net.connman.Agent" interface in order to provide the password during connection to protected access point. I'm registering the Agent like so:

GDBusMessage* methodCallMessage = g_dbus_message_new_method_call("net.connman", "/", "net.connman.Manager", "RegisterAgent");

g_dbus_message_set_body(methodCallMessage, g_variant_new ("(o)", "/test/agent"));
g_dbus_connection_send_message(connection, methodCallMessage, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error);

Also I've registered interface like the following:

guint registration_id = g_dbus_connection_register_object (connection,
                                                           "/test/agent",
                                                           introspection_data->interfaces[0],
                                                           &interface_vtable,
                                                           NULL,
                                                           NULL,
                                                           NULL);

where introspection_data is generated from XML code like below:

static const gchar introspection_xml[] =
"<node>"
"  <interface name='net.connman.Agent'>"
"    <method name='RequestInput'>"
"      <arg type='oa{sv}' name='service' direction='in'/>"
"      <arg type='a{sv}' name='fields' direction='out'/>"
"    </method>"
"  </interface>"
"</node>";
    
introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);

and interface_vtable is defined like following:

static const GDBusInterfaceVTable interface_vtable =
{
  handle_method_call,
  nullptr,
  nullptr
};

static void
handle_method_call (GDBusConnection       *connection,
                    const gchar           *sender,
                    const gchar           *object_path,
                    const gchar           *interface_name,
                    const gchar           *method_name,
                    GVariant              *parameters,
                    GDBusMethodInvocation *invocation,
                    gpointer               user_data)
{
    printf("Method called!\n");
}

Currently I'm not handling any input in my handler method, just want to see that it is called. But when I'm calling "Connect" on protected services (obtained after "Scan") I got the following output:

Call D-Bus method with reply: object = /net/connman/service/wifi_f8c091152c85_52696e6a692773206950686f6e65_managed_psk, interface = net.connman.Service, method name = Connect

(process:2929): GLib-CRITICAL **: 12:43:00.606: g_variant_type_checked_: assertion 'g_variant_type_string_is_valid (type_string)' failed

(process:2929): GLib-CRITICAL **: 12:43:00.606: g_variant_type_is_subtype_of: assertion 'g_variant_type_check (supertype)' failed

(process:2929): GLib-CRITICAL **: 12:43:00.606: g_variant_type_dup_string: assertion 'g_variant_type_check (type)' failed
Replied with error = 'GDBus.Error:net.connman.Error.InvalidArguments: Invalid arguments'

As I understand this might be the issue with the RequestInput signature, but I've only seen 'oa{sv}' for input and 'a{sv}' for output mentioned throught different articles / code examples etc.

Does anyone faced such error before?

Any suggestions and solutions would be appreciated.

Thanks.


Solution

  • Found the solution myself. It appears that the signature was indeed wrong and the right one is the following:

    static const gchar introspection_xml[] =
      "<node>"
      "  <interface name='net.connman.Agent'>"
      "    <method name='RequestInput'>"
      "      <arg name='service' type='o' direction='in'/>"
      "      <arg name='fields' type='a{sv}' direction='in'/>"
      "      <arg name='fields' type='a{sv}' direction='out'/>"
      "    </method>"
      "  </interface>"
      "</node>";