You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Connman DBus连接加密WiFi时Agent接口方法未被调用

Connman DBus Agent未触发导致Connect超时问题

我正在开发一款使用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 - 已达到超时时间

问题分析与解决步骤

  1. 修正自省XML的方法签名
    你的自省XML中RequestInput的输出参数与输入参数重名,违反DBus规范,Connman可能因此拒绝调用Agent方法。修改输出参数名:

    <arg type='a{sv}' name='response' direction='out'/>
    
  2. 确保Agent路径合法
    检查WiFiAgent::ourAgentPath是否为合法DBus对象路径,比如/com/yourcompany/WiFiAgent,路径必须以/开头,各段仅包含字母、数字、_、-。

  3. 避免同步调用阻塞事件循环
    同步调用g_dbus_proxy_call_sync会阻塞线程,若程序未运行GLib主事件循环,DBus无法派发Agent方法调用。解决方案:

    • 改用异步调用g_dbus_proxy_call,并在回调中处理结果;
    • 或在调用Connect前,启动GLib主循环(如在单独线程中运行g_main_loop_run)。
  4. 验证Agent注册正确性
    注册后用g_dbus_connection_get_object_info检查注册的接口是否为net.connman.Agent,确保introspectionWrapper->interfaces[0]指向正确接口。

  5. 检查权限配置
    用busctl测试Agent注册权限:

    busctl call net.connman / net.connman.Manager RegisterAgent o /com/yourcompany/WiFiAgent
    

    若失败,需配置Polkit规则赋予程序访问Connman的权限。

  6. 监控DBus消息排查
    用busctl monitor查看Connman是否发送Agent调用:

    busctl monitor --system net.connman
    

    若看到RequestInput调用但无响应,说明Agent处理逻辑有问题;若未发送调用,说明Agent注册失败。

内容的提问来源于stack exchange,提问作者Alvov1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 15:10:19