c++ 连接到DBus中的受保护网络时,不会调用代理接口方法

h5qlskok  于 2022-12-24  发布在  其他
关注(0)|答案(1)|浏览(140)

我正在开发一个使用Connman DBus API连接到安全WiFi网络的应用程序。我读到我需要注册一个实现net.connman.Agent接口的对象,以便DBus可以调用我的方法。到目前为止,我已经能够做一些非常接近我需要的事情,但是当我运行程序时,如果我以前从未连接到该网络,“Connect”函数超时。2如果我在代理事件处理程序上设置断点,它将永远不会被调用。3我有以下代理注册代码:

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”函数失败,并出现超时错误:
Glib错误代码为24 - g-io-error-quark -超时
我这样调用这个函数:

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;
}

网络接收的方式是:

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);
ej83mcc0

ej83mcc01#

通过将Connect方法调用更改为异步并运行主循环,设法解决了问题:

g_dbus_proxy_call(G_DBUS_PROXY(network), "Connect", g_variant_new("()"), 
    G_DBUS_CALL_FLAGS_NONE, -1, nullptr, finisher, data);
g_main_loop_run(mainloop);

if(data ... connectionFlag == false) /* Checking finisher result. */
    throw std::runtime_error("Connection failed");

分页装订器功能:

static constexpr auto finisher = [](GObject*, GAsyncResult* result, gpointer userdata) {
    auto* parameters = static_cast<...*>(userdata);
    GDBusProxy* network = parameters->...;

    GError* error = nullptr;
    GVariant* tResult = g_dbus_proxy_call_finish(G_DBUS_PROXY(network), result, &error);
    if (tResult != nullptr && error == nullptr)
        ...; /* Success, setting up the result flag. */

    g_main_loop_quit(mainloop); 
    /* Quits the main loop and unlocks the main thread */
};

现在,代理方法在Connect方法之后立即调用。

相关问题