D-Bus tutoriel en C pour communiquer avec wpa_supplicant

Je suis en train d'écrire un peu de code pour communiquer avec wpa_supplicant en utilisant DBUS. Comme je travaille dans un système embarqué (ARM), je voudrais éviter l'utilisation de Python ou de la GLib. Je me demande si je suis stupide parce que j'ai vraiment le sentiment qu'il n'est pas agréable et claire de la documentation à propos de D-Bus. Même avec l'officiel, je trouve la documentation de trop haut niveau, ou les exemples présentés sont à l'aide de Glib! La Documentation que j'ai regardé: http://www.freedesktop.org/wiki/Software/dbus

J'ai trouvé un article intéressant sur l'utilisation de D-Bus dans C: http://www.matthew.ath.cx/articles/dbus

Toutefois, cet article est assez vieux et pas assez complet! J'ai aussi trouvé le c++API dbus, mais aussi ici, je n'ai pas trouvé de documentation! J'ai fouiné dans wpa_supplicant et NetworkManager code source, mais il est tout à fait un cauchemar! J'ai été regarder dans le "bas-niveau D-Bus API" ainsi, mais cela ne me dites pas comment extraire un paramètre de chaîne de D-Bus de message! http://dbus.freedesktop.org/doc/api/html/index.html

Voici un code que j'ai écrit pour tester un peu, mais j'ai vraiment du mal à extraire les valeurs de chaîne. Désolé pour le long code source, mais si quelqu'un veut l'essayer ... Mon D-Bus configuration semble très bien, parce que "déjà" captures "StateChanged" signaux de wpa_supplicant, mais ne peut pas imprimer de l'état:

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

Un pointeur vers un joli, complet, de bas-niveau C tutoriel est fortement apprécié! Je prévois aussi de faire une certaine distance l'appel de méthode, de sorte que si le tutoriel couvre ce sujet, il serait grand! Dire que je ne suis pas très intelligent parce que je n'ai pas l'obtenir avec le tutoriel officiel est également apprécié :-p!

Ou est-il une autre façon de communiquer avec wpa_supplicant (à l'exception de l'aide wpa_cli)?

EDIT 1:

À l'aide de 'qdbusviewer' et l'introspection capabilty, cela m'a beaucoup aidé à découvrir ce que et comment wpa_supplicant fonctionne en utilisant dbus. Saut que cela aide quelqu'un d'autre!

Edit 2:

Viendra sans doute quand je vais trouver un moyen de lire les valeurs de chaîne sur D-Bus!

  • Avez-vous trouver un moyen pour lire les valeurs de chaîne sur D-Bus?
InformationsquelleAutor morandg | 2011-12-15