使用Connman DBus连接加密WiFi时Agent接口方法未被调用
我正在开发一款使用Connman DBus API连接安全WiFi网络的应用。根据文档要求,需要注册一个实现net.connman.Agent接口的对象,以便DBus调用我的方法。目前代码执行无报错,但首次连接未接入过的网络时,Connect函数超时,且Agent的事件处理函数handleMethodCall从未被触发。
相关代码片段
注册Agent的代码
WiFiAgent::WiFiAgent(GDBusConnection *inputConnection, Poco::JSON::Object::Ptr credentials) : connection(inputConnection), parameters(std::move(credentials)) { static const GDBusInterfaceVTable vtable = { .method_call = handleMethodCall, .get_property = nullptr, .set_property = nullptr, }; static GError* error = nullptr; objectId = g_dbus_connection_register_object( connection, WiFiAgent::ourAgentPath, WiFiAgent::introspectionWrapper->interfaces[0], &vtable, parameters.get(), nullptr, &error ); if(objectId == 0 || error != nullptr) throw GlibException("Register WiFi agent", error); GVariant* agentPathVariant = g_variant_new("(o)", WiFiAgent::ourAgentPath); if(agentPathVariant == nullptr) throw std::runtime_error("Register WiFi agent: g_variant_new failed."); GVariant* result = g_dbus_connection_call_sync(connection, "net.connman", "/", "net.connman.Manager", "RegisterAgent", agentPathVariant, nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); if(result == nullptr || error != nullptr) throw GlibException("Register WiFi agent", error); }
事件处理函数代码
void WiFiAgent::handleMethodCall(GDBusConnection *, const gchar *, const gchar *, const gchar *, const gchar *method, GVariant *methodParameters, GDBusMethodInvocation *invocation, gpointer userdata) { std::cout << "Method got called." << std::endl; }
自省代码
static inline class IntrospectionWrapper final { GDBusNodeInfo* introspection = nullptr; static constexpr auto introspectionXML = "<node>" " <interface name='net.connman.Agent'>" " <method name='RequestInput'>" " <arg type='o' name='service' direction='in'/>" " <arg type='a{sv}' name='fields' direction='in'/>" " <arg type='a{sv}' name='fields' direction='out'/>" " </method>" " <method name='ReportError'>" " <arg type='o' name='service' direction='in'/>" " <arg type='s' name='error' direction='in'/>" " </method>" " </interface>" "</node>"; public: IntrospectionWrapper() { GError* error = nullptr; introspection = g_dbus_node_info_new_for_xml(introspectionXML, &error); if(introspection == nullptr || error != nullptr) std::cerr << GlibException("Agent introspection construction", error) << std::endl; } GDBusNodeInfo* operator->() { return introspection; }; GDBusNodeInfo* get() { return introspection; } } introspectionWrapper;
调用Connect的代码
void DBusManipulator::connectToTheNetwork(GDBusProxy *network) { GError* error = nullptr; g_dbus_proxy_call_sync(network, "Connect", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); if(error != nullptr) throw GlibException("Connect to the network", error); const auto state = variantGetValue(getNetworkProperty(network, "State")); if(state != "online" && state != "ready") throw std::runtime_error("Connect to the WiFi network: connection failed"); std::cout << "Connected to the network successfully." << std::endl; }
获取network对象的代码
GDBusProxy* network = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, nullptr, "net.connman", servicePath, "net.connman.Service", nullptr, &error); if(network == nullptr || error != nullptr) throw GlibException("Get network by name", error);
报错信息
Glib错误,错误码24 - g-io-error-quark - 已达到超时时间
问题分析与解决步骤
修正自省XML的方法签名
你的自省XML中RequestInput的输出参数与输入参数重名,违反DBus规范,Connman可能因此拒绝调用Agent方法。修改输出参数名:<arg type='a{sv}' name='response' direction='out'/>确保Agent路径合法
检查WiFiAgent::ourAgentPath是否为合法DBus对象路径,比如/com/yourcompany/WiFiAgent,路径必须以/开头,各段仅包含字母、数字、_、-。避免同步调用阻塞事件循环
同步调用g_dbus_proxy_call_sync会阻塞线程,若程序未运行GLib主事件循环,DBus无法派发Agent方法调用。解决方案:- 改用异步调用
g_dbus_proxy_call,并在回调中处理结果; - 或在调用
Connect前,启动GLib主循环(如在单独线程中运行g_main_loop_run)。
- 改用异步调用
验证Agent注册正确性
注册后用g_dbus_connection_get_object_info检查注册的接口是否为net.connman.Agent,确保introspectionWrapper->interfaces[0]指向正确接口。检查权限配置
用busctl测试Agent注册权限:busctl call net.connman / net.connman.Manager RegisterAgent o /com/yourcompany/WiFiAgent若失败,需配置Polkit规则赋予程序访问Connman的权限。
监控DBus消息排查
用busctl monitor查看Connman是否发送Agent调用:busctl monitor --system net.connman若看到
RequestInput调用但无响应,说明Agent处理逻辑有问题;若未发送调用,说明Agent注册失败。
内容的提问来源于stack exchange,提问作者Alvov1

