2011-12-15 9 views
17

Próbuję napisać kod do komunikacji z wpa_supplicant przy użyciu DBUS. Ponieważ pracuję w systemie wbudowanym (ARM), chciałbym uniknąć użycia Pythona lub GLib. Zastanawiam się, czy jestem głupi, bo naprawdę mam wrażenie, że nie ma ładnej i jasnej dokumentacji na temat D-Bus. Nawet w przypadku oficjalnej wersji albo znajduję dokumentację zbyt wysokiego poziomu, albo pokazane przykłady używają Glib! Dokumentacja Sprawdziliśmy: http://www.freedesktop.org/wiki/Software/dbusSamouczek D-Bus w C do komunikacji z wpa_supplicant

Znalazłem ciekawy artykuł na temat korzystania z D-Bus w C: http://www.matthew.ath.cx/articles/dbus

Jednakże, ten artykuł jest dość stary i nie zakończyć wystarczy! Znalazłem także C++ - dbus API, ale także tutaj, nie znajduję ŻADNEJ dokumentacji! Wkopiam się w kod źródłowy wpa_supplicant i NetworkManager, ale jest to koszmar! Zajmuję się również "niskopoziomowym interfejsem D-Bus API", ale to nie mówi mi, jak wyodrębnić parametr łańcuchowy z komunikatu D-Bus! http://dbus.freedesktop.org/doc/api/html/index.html

Oto trochę kodu, który napisałem, aby przetestować trochę, ale naprawdę mam problem z wyodrębnieniem wartości ciągu. Przepraszam za długi kodu źródłowego, ale jeśli ktoś chce spróbować ... Moja konfiguracja D-Bus wydaje się w porządku, ponieważ „już” łapie „StateChanged” sygnały z wpa_supplicant ale nie można wydrukować stan:

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

Każda wskazówka do miłego, kompletnego, niskiego poziomu poradnika C jest bardzo doceniany! Planuję również wykonać zdalne wywołanie metody, więc jeśli samouczek omawia ten temat, byłoby świetnie! Powiedzenie, że nie jestem zbyt mądry, ponieważ nie rozumiem tego z oficjalnym samouczkiem, jest również mile widziane :-p!

Czy istnieje inny sposób komunikacji z wpa_supplicant (z wyjątkiem korzystania z wpa_cli)?

EDIT 1:

Korzystanie 'qdbusviewer' i capabilty introspekcji to bardzo mi pomogło odkrywania tego, co i jak wpa_supplicant prace przy użyciu dbus. Mając nadzieję, że to pomoże komuś innemu!

Edit 2:

będzie prawdopodobnie pochodzić kiedy Znajdę sposób odczytać wartości ciągów o D-Bus!

+0

Znaleźliście sposób odczytywania wartości ciągów na D-Bus? –

Odpowiedz

1
+0

martwy link ....... –

+2

Podczas gdy ten link może odpowiedzieć na pytanie, lepiej umieścić tutaj istotne części odpowiedzi i podać odnośnik. Odpowiedzi dotyczące linków mogą stać się nieprawidłowe, jeśli strona z linkami się zmieni. - [Z recenzji] (/ opinia/niskiej jakości-posts/18892083) – Boiethios

2

Nie trzeba używać/zrozumieć pracę z dbus Jeśli wystarczy napisać program w C do komunikowania się z wpa_supplicant. Odwzorowałem kod źródłowy wpa_cli. Przeprowadzono jego implementację i wykorzystano funkcje podane w wpa_ctrl.h/c. Ta implementacja zajmuje się wszystkim. Możesz użyć/zmodyfikować cokolwiek chcesz, skompiluj swój plik wykonywalny i gotowe!

Oto oficjalna Link do ctrl_interface wpa_supplicant jest: http://hostap.epitest.fi/wpa_supplicant/devel/ctrl_iface_page.html

+0

Dobrze. Użyłem tego samego podejścia. Wszystko jest w wpa_cli.c i wpa_ctrl.h dla kopiowania/wklejania.Interfejs sterowania jest zalecanym sposobem komunikowania się z wpa_supplicant, jak w powyższym linku. Nie musisz walczyć z d-bus. – FractalSpace

4

Dałeś się narzędzia, które pomogą Ci nauczyć się D-Bus łatwiej i korzystają realizację niski poziom libdbus, więc może zasługują na w bólu. BTW, czy mówisz o ARM, jak ARM telefonu komórkowego? Może z 500 Mhz i 256 MB pamięci RAM? W tym przypadku procesor dobrze nadaje się do używania glib, Qt, a nawet python. A D-Bus jest najbardziej przydatny, gdy piszesz asynchroniczny kod sterowany zdarzeniami, ze zintegrowaną pętlą główną, na przykład z glib, nawet jeśli używasz libdbus niskiego poziomu (ma on funkcje łączenia się z główną pętlą glib, na przykład).

Ponieważ używasz biblioteki niskim poziomie, a następnie dokumentacja jest to, co już masz:

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

również kod źródłowy libdbus jest również częścią dokumentacji:

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

Głównym punktem wejścia do dokumentacji jest strona Moduły (w szczególności sekcja publicznego interfejsu API):

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

Do obsługi wiadomości, DBusMessage sekcja jest odpowiednia jeden: DBusMessage

Nie masz w dokumentacji funkcji analizowania wartości elementu. W twoim przypadku zaczynałeś od dbus_message_iter_get_basic. Jak opisano w dokumentach, pobranie ciągu wymaga zmiennej const char **, ponieważ zwrócona wartość wskaże wstępnie przydzielony ciąg w odebranej wiadomości:

Tak więc dla int32 powinien to być "dbus_int32_t *" i dla napisu "const char **". Zwrócona wartość jest odniesieniem i nie powinna zostać zwolniona.

Nie można zdefiniować tablicy, ponieważ libdbus nie skopiuje tekstu do tablicy. Jeśli chcesz zapisać ciąg, najpierw pobierz stałe odwołanie do łańcucha, a następnie przejdź do własnej tablicy.

Następnie próbowano uzyskać stałą tablicę bez przenoszenia iteratora. Potrzebujesz wywołania do następnego iteratora (dbus_message_iter_next) pomiędzy podstawowym łańcuchem a stałą tablicą. To samo tuż przed powrotem do podt itera.

Wreszcie, nie wywołujemy get_array_len, aby uzyskać liczbę elementów w tablicy. Z dokumentów zwraca tylko liczbę bajtów. Zamiast tego przegląda się iterator podrzędny za pomocą iter_next w ten sam sposób, w jaki powinieneś zrobić z głównym iteratorem. Po zakończeniu iteracji po końcu tablicy dbus_message_iter_get_arg_type zwróci DBUS_TYPE_INVALID.

Aby uzyskać więcej informacji, zapoznaj się z podręcznikiem użytkownika, nie szukaj samouczka. Lub po prostu użyć rozsądny realizację d-bus:

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

Gio za GDBus automatycznie tworzy obwoluty dla połączeń d-bus.

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

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

itp

0

Poniższy fragment działa na mnie

if (argType == DBUS_TYPE_STRING) 
{ 
printf("Got string argument, extracting ...\n"); 
char* strBuffer = NULL; 
dbus_message_iter_get_basic(&args, &strBuffer); 
printf("Received string: \n %s \n",strBuffer); 

}