D-Bus教程在C中与wpa_supplicant通信 [英] D-Bus tutorial in C to communicate with wpa_supplicant

查看:197
本文介绍了D-Bus教程在C中与wpa_supplicant通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用DBUS编写一些代码与wpa_supplicant进行通信。当我在嵌入式系统(ARM)中工作时,我想避免使用Python或GLib。我想知道如果我很笨,因为我真的有这样的感觉,没有关于D-Bus的漂亮和清晰的文档。即使是官方的,我也可能发现文档太高级别,或者示例使用的是Glib!我看过的文档: http://www.freedesktop.org/wiki/Software/dbus

I'm trying to write some code to communicate with wpa_supplicant using DBUS. As I'm working in an embedded system (ARM), I'd like to avoid the use of Python or the GLib. I'm wondering if I'm stupid because I really have the feeling that there is no nice and clear documentation about D-Bus. Even with the official one, I either find the documentation too high level, or the examples shown are using Glib! Documentation I've looked at: http://www.freedesktop.org/wiki/Software/dbus

我发现一篇关于在C中使用D-Bus的好文章: http: //www.matthew.ath.cx/articles/dbus

I found a nice article about using D-Bus in C: http://www.matthew.ath.cx/articles/dbus

但是,这篇文章很旧,还不够完整!我也发现了c ++ - dbus API,但是在这里我没有找到任何文档!我一直在挖掘wpa_supplicant和NetworkManager源代码,但这是一个噩梦!我一直在研究低级D-Bus API,但这并不告诉我如何从D-Bus消息中提取字符串参数! http://dbus.freedesktop.org/doc/api/html/index.html

However, this article is pretty old and not complete enough! I also found the c++-dbus API but also here, I don't find ANY documentation! I've been digging into wpa_supplicant and NetworkManager source code but it's quite a nightmare! I've been looking into the "low-level D-Bus API" as well but this doesn't tell me how to extract a string parameter from a D-Bus message! http://dbus.freedesktop.org/doc/api/html/index.html

这是我写的一些代码来测试一下,但是我真的很难提取字符串值。很抱歉,长的源代码,但如果有人想尝试...我的D-Bus配置似乎很好,因为它已经捕获来自wpa_supplicant的StateChanged信号,但不能打印状态:

Here is some code I wrote to test a little but I really have trouble to extract string values. Sorry for the long source code but if someone want to try it ... My D-Bus configuration seems fine because it "already" catches "StateChanged" signals from wpa_supplicant but cannot print the state:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

#include <dbus/dbus.h>

//#include "wpa_supp_dbus.h"
/* Content of wpa_supp_dbus.h */
#define WPAS_DBUS_SERVICE   "fi.epitest.hostap.WPASupplicant"
#define WPAS_DBUS_PATH      "/fi/epitest/hostap/WPASupplicant"
#define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant"

#define WPAS_DBUS_PATH_INTERFACES   WPAS_DBUS_PATH "/Interfaces"
#define WPAS_DBUS_IFACE_INTERFACE   WPAS_DBUS_INTERFACE ".Interface"

#define WPAS_DBUS_NETWORKS_PART "Networks"
#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network"

#define WPAS_DBUS_BSSIDS_PART   "BSSIDs"
#define WPAS_DBUS_IFACE_BSSID   WPAS_DBUS_INTERFACE ".BSSID"

int running = 1;

void stopLoop(int sig)
{
    running = 0;
}

void sendScan()
{
  // TODO !
}

void loop(DBusConnection* conn)
{
    DBusMessage* msg;
    DBusMessageIter args;
    DBusMessageIter subArgs;
    int argType;
    int i;
    int buffSize = 1024;
    char strValue[buffSize];
    const char* member = 0;

    sendScan();

    while (running)
    {
        // non blocking read of the next available message
        dbus_connection_read_write(conn, 0);
        msg = dbus_connection_pop_message(conn);

        // loop again if we haven't read a message
        if (!msg)
        {
            printf("No message received, waiting a little ...\n");
            sleep(1);
            continue;
        }
        else printf("Got a message, will analyze it ...\n");

        // Print the message member
        printf("Got message for interface %s\n",
                dbus_message_get_interface(msg));
        member = dbus_message_get_member(msg);
        if(member) printf("Got message member %s\n", member);

        // Check has argument
        if (!dbus_message_iter_init(msg, &args))
        {
            printf("Message has no argument\n");
            continue;
        }
        else
        {
            // Go through arguments
            while(1)
            {
                argType = dbus_message_iter_get_arg_type(&args);

                if (argType == DBUS_TYPE_STRING)
                {
                    printf("Got string argument, extracting ...\n");

                    /* FIXME : got weird characters
                    dbus_message_iter_get_basic(&args, &strValue);
                    */

                    /* FIXME : segmentation fault !
                    dbus_message_iter_get_fixed_array(
                            &args, &strValue, buffSize);
                    */

                    /* FIXME : segmentation fault !
                    dbus_message_iter_recurse(&args, &subArgs);
                    */

                    /* FIXME : deprecated!
                    if(dbus_message_iter_get_array_len(&args) > buffSize)
                        printf("message content to big for local buffer!");
                    */

                    //printf("String value was %s\n", strValue);
                }
                else
                    printf("Arg type not implemented yet !\n");

                if(dbus_message_iter_has_next(&args))
                    dbus_message_iter_next(&args);
                else break;
            }
            printf("No more arguments!\n");
        }

        // free the message
        dbus_message_unref(msg);
    }
}

int main(int argc, char* argv[])
{
    DBusError err;
    DBusConnection* conn;
    int ret;
    char signalDesc[1024];     // Signal description as string

    // Signal handling
    signal(SIGKILL, stopLoop);
    signal(SIGTERM, stopLoop);

    // Initialize err struct
    dbus_error_init(&err);

    // connect to the bus
    conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
    if (dbus_error_is_set(&err))
    {
        fprintf(stderr, "Connection Error (%s)\n", err.message);
        dbus_error_free(&err);
    }
    if (!conn)
    {
        exit(1);
    }

    // request a name on the bus
    ret = dbus_bus_request_name(conn, WPAS_DBUS_SERVICE, 0, &err);
    if (dbus_error_is_set(&err))
    {
        fprintf(stderr, "Name Error (%s)\n", err.message);
        dbus_error_free(&err);
    }

    /* Connect to signal */
    // Interface signal ..
    sprintf(signalDesc, "type='signal',interface='%s'",
            WPAS_DBUS_IFACE_INTERFACE);
    dbus_bus_add_match(conn, signalDesc, &err);
    dbus_connection_flush(conn);
    if (dbus_error_is_set(&err))
    {
        fprintf(stderr, "Match Error (%s)\n", err.message);
        exit(1);
    }

    // Network signal ..
    sprintf(signalDesc, "type='signal',interface='%s'",
            WPAS_DBUS_IFACE_NETWORK);
    dbus_bus_add_match(conn, signalDesc, &err);
    dbus_connection_flush(conn);
    if (dbus_error_is_set(&err))
    {
        fprintf(stderr, "Match Error (%s)\n", err.message);
        exit(1);
    }

    // Bssid signal ..
    sprintf(signalDesc, "type='signal',interface='%s'",
            WPAS_DBUS_IFACE_BSSID);
    dbus_bus_add_match(conn, signalDesc, &err);
    dbus_connection_flush(conn);
    if (dbus_error_is_set(&err))
    {
        fprintf(stderr, "Match Error (%s)\n", err.message);
        exit(1);
    }

    // Do main loop
    loop(conn);

    // Main loop exited
    printf("Main loop stopped, exiting ...\n");

    dbus_connection_close(conn);

    return 0;
}

任何指向任何好的,完整的低级C教程的指针都非常感谢!我也打算做一些远程方法调用,所以如果教程涵盖这个主题,这将是非常好的!说我不是很聪明,因为我没有得到它的官方教程也赞赏:-p!

Any pointer to any nice, complete, low-level C tutorial is strongly appreciated! I'm also planning to do some remote method call, so if the tutorial covers this subject it would be great! Saying I'm not very smart because I don't get it with the official tutorial is also appreciated :-p!

还是有另一种方式与wpa_supplicant(除了使用wpa_cli)?

Or is there another way to communicate with wpa_supplicant (except using wpa_cli)?

编辑1:

使用qdbusviewer和内省的能力,这帮助我很多发现什么和如何wpa_supplicant工作使用dbus。希望这可以帮助别人!

Using 'qdbusviewer' and the introspection capabilty, this helped me a lot discovering what and how wpa_supplicant works using dbus. Hopping that this would help someone else!

编辑2:

来,当我找到一种方法来读取D-Bus上的字符串值!

Will probably come when I'll find a way to read string values on D-Bus!

推荐答案

你已经放弃了帮助您更轻松地学习D-Bus,并使用低级别的libdbus实现,所以也许你值得痛苦。 BTW,你在说ARM,像手机ARM?可能有500 Mhz和256 MB RAM?在这种情况下,处理器非常适合使用glib,Qt甚至python。当您编写异步事件驱动代码时,D-Bus最为有用,例如使用glib的集成主循环,即使您使用低级别的libdbus(它具有连接到glib主循环的功能)例如)

You have given up the tools that would help you to learn D-Bus more easily and are using the low level libdbus implementation, so maybe you deserve to be in pain. BTW, are you talking about ARM, like a cell phone ARM ? With maybe 500 Mhz and 256 MB RAM ? In this case the processor is well suited to using glib, Qt or even python. And D-Bus is most useful when you're writing asynchronous event driven code, with an integrated main loop, for example from glib, even when you're using the low level libdbus (it has functions to connect to the glib main loop, for example).

由于您使用的是低级库,所以文档就是您已经拥有的:

Since you're using the low level library, then documentation is what you already have:

http://dbus.freedesktop.org/doc/api/html/index .html

此外,libdbus源代码也是文档的一部分:

Also, libdbus source code is also part of the documentation:

http://dbus.freedesktop.org/doc/api/html/files.html

文档的主要入口点是模块页面(特别是公共API部分):

The main entry point for the documentation is the Modules page (in particular, the public API section):

http://dbus.freedesktop.org/doc/api/html/模块.html

对于消息处理,DBusMessage部分是相关的:
DBusMessage

For message handling, the section DBusMessage is the relevant one: DBusMessage

您有文档解析项目值的功能。在你的情况下,你开始使用一个dbus_message_iter_get_basic。如文档中所述,检索字符串需要一个const char **变量,因为返回的值将指向接收到的消息中预分配的字符串:

There you have the documentation for functions that parse item values. In your case, you started with a dbus_message_iter_get_basic. As described in the docs, retrieving the string requires a const char ** variable, since the returned value will point to the pre-allocated string in the received message:

所以对于int32,它应该是一个dbus_int32_t *,对于字符串const char **。返回的值是引用的,不应该被释放。
So for int32 it should be a "dbus_int32_t*" and for string a "const char**". The returned value is by reference and should not be freed.

所以你不能定义一个数组,因为libdbus不会将文本复制到你的数组中。如果您需要保存字符串,首先得到常量字符串引用,然后将strcpy转换为您自己的数组。

So you can't define an array, because libdbus won't copy the text to your array. If you need to save the string, first get the constant string reference, then strcpy to your own array.

然后,您尝试获取固定数组而不移动迭代器。您需要调用基本字符串和固定数组之间的下一个迭代器(dbus_message_iter_next)。在递归到子迭代器之前就一样。

Then you tried to get a fixed array without moving the iterator. You need a call to the next iterator (dbus_message_iter_next) between the basic string and the fixed array. Same right before recursing into the sub iterator.

最后,您不要调用get_array_len来获取数组上的元素数。从文档中,它只返回字节计数。相反,您可以使用iter_next循环遍历子迭代器,方法与主迭代器相同。在数组结束之后,dbus_message_iter_get_arg_type将返回DBUS_TYPE_INVALID。

Finally, you don't call get_array_len to get the number of elements on the array. From the docs, it only returns byte counts. Instead you loop over the sub iterator using iter_next the same way you should have done with the main iterator. After you have iterated past the end of the array, dbus_message_iter_get_arg_type will return DBUS_TYPE_INVALID.

有关更多信息,请参阅参考手册,不要寻找教程。或者只是使用合理的d-bus实现:

For more info, read the reference manual, don't look for a tutorial. Or just use a reasonable d-bus implementation:

https://developer.gnome.org/gio/2.36/gdbus-codegen.html

GIO的GDBus自动创建包装器您的d-bus电话。

GIO's GDBus automatically creates wrappers for your d-bus calls.

http://qt-project.org/doc/qt-4.8/intro-to-dbus.html

http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial .html

等。

这篇关于D-Bus教程在C中与wpa_supplicant通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆