2011-12-15 2 views
17

DBUS를 사용하여 wpa_supplicant와 통신하기위한 코드를 작성하려고합니다. 임베디드 시스템 (ARM)에서 일하기 때문에 파이썬이나 GLib의 사용을 피하고 싶습니다. 나는 D-Bus에 대한 훌륭하고 명확한 문서가 없다는 느낌을 실제로 받기 때문에 바보인지 궁금해하고 있습니다. 공식적인 문서 일지라도 문서가 너무 높은 수준으로 발견되거나 표시된 예제가 Glib을 사용하고 있습니다! http://www.freedesktop.org/wiki/Software/dbusC에서 D-Bus 자습서를 사용하여 wpa_supplicant와 통신하십시오.

내가 C에서 D-버스를 사용에 대한 좋은 기사를 발견 : 문서는 내가 검토 한 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

다음은 약간의 테스트를 위해 작성한 코드이지만 실제로는 문자열 값을 추출하는 데 어려움이 있습니다. 긴 소스 코드에 대한 죄송하지만 누군가는 "이미"어획량이 wpa_supplicant를에서 신호를 "따라서, stateChanged"있기 때문에 ... 내 D-버스 구성이 잘 보인다 시도하고 싶지만 상태 인쇄 할 수없는 경우 :

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

wpa_supplicant와 통신하는 또 다른 방법이 있습니까 (wpa_cli 사용 제외).

편집 1 :

'qdbusviewer'과 반성의 capabilty을 사용하여,이 DBUS를 사용하여 무엇을 어떻게 wpa_supplicant를 작품을 발견하는 나에게 많은 도움이되었습니다. 이 호핑은 다른 사람을 도울 것입니다!

편집 2 :

나는 D-버스에 문자열 값을 읽을 수있는 방법을 찾을 때

아마 올 것이다!

+0

당신이 D-버스에 문자열 값을 읽을 수있는 방법을 찾았나요? –

답변

1

는이 같은 종류의 의미 : 당신은 그냥 wpa_supplicant를 통신하는 C 프로그램을 작성해야하는 경우 http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap-1.git;a=tree;f=wpa_supplicant;h=5e71ad2d72cef4a59842cb6c91a116ae4997ddd1;hb=HEAD

+0

죽은 링크 ....... –

+2

이 링크가 질문에 대답 할 수 있지만 여기에 답변의 핵심 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않게 될 수 있습니다. - [리뷰에서] (리뷰/저품절 포스트/18892083) – Boiethios

2

당신은/사용 DBUS의 작업을 이해 할 필요가 없습니다. 나는 wpa_cli의 소스 코드를 리버스 엔지니어링했다. wpa_ctrl.h/c에서 제공되는 구현 및 사용 된 기능을 살펴 보았습니다. 이 구현은 모든 것을 처리합니다. 원하는 것을 사용하거나 수정할 수 있으며 실행 파일을 빌드하면 완료됩니다! 당신은, 당신은 더 쉽게 D-버스를 배울 도움이 될 및 낮은 수준의 libdbus가 구현을 사용하고있는 도구를 포기 http://hostap.epitest.fi/wpa_supplicant/devel/ctrl_iface_page.html

+0

오른쪽. 나는 같은 접근법을 사용했다. 모든 것은 복사/붙여 넣기를위한 wpa_cli.c와 wpa_ctrl.h에 있습니다.위의 링크에 따라 wpa_supplicant와 통신하는 데는 제어 인터페이스가 권장됩니다. d- 버스로 고생 할 필요가 없습니다. – FractalSpace

4

어쩌면 당신이 될 자격 :

여기에 wpa_supplicant를의 ctrl_interface에 공식 링크입니다 고통. BTW, 당신은 ARM에 대해 이야기하고 있습니까? 아마 500 Mhz 및 256 MB RAM이 있습니까? 이 경우 프로세서는 glib, Qt 또는 심지어 파이썬을 사용하는 데 적합합니다. 그리고 D-Bus는 저수준 libdbus (glib main 루프에 연결하는 함수를 가지고있을 때조차도, glib에서와 같이 메인 루프가 통합 된 비동기 이벤트 구동 코드를 작성할 때 가장 유용합니다. 예를 들어).

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

:

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

은 libdbus가 소스 코드는 문서의 일부입니다

당신은 낮은 수준의 라이브러리를 사용하고 있기 때문에, 그럼 문서는 당신이 이미 가지고있는 것입니다

설명서의 주요 진입 점은 모듈 페이지 (특히 공개 API 섹션)입니다.

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

는 메시지 처리의 경우, 섹션 DBusMessage은 관련 하나입니다 :이 DBusMessage

당신이 항목의 값을 구문 분석 기능에 대한 설명서가 있습니다. 귀하의 경우 dbus_message_iter_get_basic으로 시작했습니다. 문서에서 설명한 것처럼 반환 된 값은받은 메시지의 미리 할당 된 문자열을 가리킬 것이므로 문자열을 검색하려면 const char ** 변수가 필요합니다.

따라서 int32의 경우 "dbus_int32_t *"이어야하고 문자열에 대해 "const char **". 반환 된 값은 참조 용이며 해제하면 안됩니다.

그래서 libdbus는 텍스트를 배열에 복사하지 않으므로 배열을 정의 할 수 없습니다. 문자열을 저장해야하는 경우 먼저 상수 문자열 참조를 가져온 다음 strcpy를 자신의 배열에 가져옵니다.

그런 다음 이터레이터를 이동하지 않고 고정 된 배열을 얻으려고했습니다. 기본 문자열과 고정 배열 사이의 다음 반복자 (dbus_message_iter_next)를 호출해야합니다. 서브 반복자로 재귀 적으로 돌아 가기 전에 똑같이.

마지막으로 배열의 요소 수를 얻기 위해 get_array_len을 호출하지 마십시오. 문서에서는 바이트 수만 반환합니다. 대신 iter_next를 사용하여 하위 iterator를 반복합니다. 배열의 끝을 지나서 반복하면 dbus_message_iter_get_arg_type이 DBUS_TYPE_INVALID를 반환합니다.

자세한 내용은 참조 설명서를 읽고 자습서를 찾지 마십시오. 아니면 그냥 합리적인 D-버스 구현을 사용

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

GIO의 GDBus 자동으로 D-버스 통화에 대해 래퍼를 생성합니다.

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

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

아래의 코드 조각은 나를 위해 작동
0

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

}