Учебник по D-Bus на C для связи с wpa_supplicant

Я пытаюсь написать код для связи с wpa_supplicant с помощью DBUS. Поскольку я работаю во встроенной системе (ARM), я бы не хотел использовать Python или GLib. Мне интересно, не глуп ли я, потому что у меня действительно такое чувство, что нет хорошей и ясной документации о D-Bus. Я считаю, что даже официальная документация слишком высока, или в приведенных примерах используется Glib! Документация, которую я просмотрел: http://www.freedesktop.org/wiki/Software/dbus

Я нашел хорошую статью об использовании D-Bus в C: http: // www. matthew.ath.cx / article / dbus

Однако эта статья довольно старая и недостаточно полная! Я также нашел c ++ - dbus API, но и здесь, я не нашел НИКАКОЙ документации! Я копался в исходном коде wpa_supplicant и NetworkManager, но это настоящий кошмар! Я тоже изучал «низкоуровневый API D-Bus», но он не говорит мне, как извлечь строковый параметр из сообщения D-Bus! http://dbus.freedesktop.org/doc/api/html/index.html

Вот код, который я написал для небольшого тестирования, но у меня действительно проблемы с извлечением строковых значений. Извините за длинный исходный код, но если кто-то захочет попробовать ... Моя конфигурация D-Bus кажется хорошей, потому что она «уже» улавливает сигналы «StateChanged» от wpa_supplicant, но не может распечатать состояние:

#include 
#include 
#include 
#include 
#include 

#include 

//#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!

Или есть другой способ связи с wpa_supplicant (кроме использования wpa_cli)?

РЕДАКТИРОВАТЬ 1:

Использование qdbusviewer и возможности самоанализа очень помогло мне узнать, что и как wpa_supplicant работает с использованием dbus. Надеясь, что это поможет кому-то другому!

Edit 2:

Вероятно, появится, когда я найду способ читать строковые значения на D-Bus!

17
задан markw 22 February 2015 в 02:37
поделиться