Ted's Blog

Happy coding

dbus基础

Ted posted @ 2008年8月16日 01:42 in 未分类 with tags dbus , 7488 阅读

这是以前学习dbus时候写的使用dbus API来接收消息的一个比较全的例子,目的是熟悉dbus的c api的功能。今天又温习了一下,贴出来永久保留:), 有时间把原理写下,kde4都用它了,应该很重要。
/**
* the demo is to demonstrate the whole process of setting up
* a dbus message loop manually. for simplicity, we connect to
* session bus instead of coding a server from the grand up.
* the best of dbus is that we can register our own callbacks in
* all most every step of message process. by using notify functions
* the main loop of application awares of the changes, including coming
* of raw message data from the transport, new outgoing message, incoming
* message queue is empty and so on.
*/
#include dbus/dbus.h>
#include stdbool.h>
#include unistd.h>
#include stdio.h>
#include stdlib.h>
#include stdarg.h>
#include string.h>
#include sys/select.h>
/**
* for every connection, there is a transport mechanism ( here
* maybe is unix domain socket ). data come and go from the connection,
* a watch is used to monitor incoming or outgoing data flow or exception.
* a watch bind with a fd (i know here fd is owned by the socket),
* when fd is ready to read data or write from transport, a notify
* event occurs.
*/
struct watchlist_t {
    DBusWatch *watch;
    struct watchlist_t *next;
};
static struct watchlist_t *watchlist = NULL;
/**
* when you send a message typed method_call with a reply, you
* may need to set up a timeout handler. when a reply available,
* a timeout event ocurrs.
*/
static struct timeoutlist_t {
    DBusTimeout *timeout;
    struct timeoutlist_t *next;
} *timeoutlist = NULL;
/**
* you can register any path you like, just follow the dbus specification,
* such as "/org", "/org/redflag", "/com" etc. i think dbus internally
* splits all path into components ("org", "redflag", "com") and arranges
* them into a tree, every node bind a handler. if one node has no
* handler registered, it processed by dbus( use
* DBUS_HANDLER_RESULT_NOT_YET_HANDLED to notify dbus).
*/
char *objectPaths[] = {
    "/org/freedesktop",
    "/com",
    "/com/redflag",
    "/org/freedesktop/DBus",
    "/org/freedesktop/csy",
    "/com/redflag/csy"
};
/** object handlers and object path handlers */
DBusHandlerResult object_dbus_handler(DBusConnection*, DBusMessage*, void*);
DBusHandlerResult object_csy_handler(DBusConnection*, DBusMessage*, void*);
DBusHandlerResult subsection_com_redflag_handler(DBusConnection*,
        DBusMessage*, void*);
DBusHandlerResult subsection_com_handler(DBusConnection*,
        DBusMessage*, void*);
DBusHandlerResult subsection_org_freedesktop_handler(DBusConnection*,
        DBusMessage*, void*);
void object_unregister_handler(DBusConnection*, void*);
DBusObjectPathVTable objectPathVTable[] = {
    {
        .unregister_function = NULL,
        .message_function = subsection_org_freedesktop_handler
    },
    {   
        .unregister_function = NULL,
        .message_function = subsection_com_handler
    },
    {
        .unregister_function = NULL,
        .message_function = subsection_com_redflag_handler
    },
    {
        .unregister_function = NULL,
        .message_function = object_dbus_handler
    },
    {
        .unregister_function = object_unregister_handler,
        .message_function = object_csy_handler
    },
    {
        .unregister_function = object_unregister_handler,
        .message_function = object_csy_handler
    }
};
static struct seriallist_t {
    dbus_uint32_t serial;
    struct seriallist_t *next;
} *seriallist = NULL;
/**------------- debug facilities --------------------------------*/
void err_quit(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    fprintf(stderr, fmt, args);
    va_end(args);
    exit(1);   
}
/**
* for debug purpose
*/
char* _verbose_watch(DBusWatch *watch) {
    char *s_flags[] = {
        "readable",
        "writable"
    };
    char p[1024] = "", ret[1024] = "";
    if (dbus_watch_get_flags(watch) & DBUS_WATCH_READABLE )
        strncpy(p, s_flags[0], strlen(s_flags[0]));
    else if (dbus_watch_get_flags(watch) & DBUS_WATCH_WRITABLE ) {
        if ( p[0] )
            strncat(p, "&", strlen("&"));
        strncat(p, s_flags[1], strlen(s_flags[1]));
    }
    sprintf(ret, ":%s", dbus_watch_get_fd(watch), p);
    return ret;
}
char* _verbose_message(DBusMessage *msg) {
    char s_msg[1024] = "", ret[1024] = "";
    int bc = sprintf(s_msg, "\ttype: %s\n\tpath: %s\n"
            "\tmember: %s\n\t",
            dbus_message_type_to_string(dbus_message_get_type(msg)),
            dbus_message_get_path(msg),
            dbus_message_get_member(msg));
    strncpy(ret, s_msg, bc+1);
   
    if (dbus_message_get_serial(msg)) {
        bc = sprintf(s_msg, "serial: %ud\n\t",
                dbus_message_get_serial(msg));
        strncat(ret, s_msg, bc+1);
    }
    if (dbus_message_get_reply_serial(msg)) {
        bc = sprintf(s_msg, "reply_serial: %ud\n\t",
                dbus_message_get_reply_serial(msg));
        strncat(ret, s_msg, bc+1);
    }
    DBusMessageIter args, subargs;
    char *s;
    int i;
    dbus_message_iter_init(msg, &args);
    bc = sprintf(s_msg, "args: ");
    strncat(ret, s_msg, bc+1);
    /** here is not the best way to parse the params, i just want to test some of
     * nested situations and different types of params. */
    while (DBUS_TYPE_INVALID != dbus_message_iter_get_arg_type(&args)) {
        // demo here: only care about int and string, igore other types
        switch (dbus_message_iter_get_arg_type(&args)) {
        case DBUS_TYPE_STRING:
            dbus_message_iter_get_basic(&args, &s);
            bc = sprintf(s_msg, " %s", s);
            strncat(ret, s_msg, bc+1);
            break;
        case DBUS_TYPE_INT32:
            dbus_message_iter_get_basic(&args, &i);
            bc = sprintf(s_msg, " %d", i);
            strncat(ret, s_msg, bc+1);
            break;
        case DBUS_TYPE_ARRAY:
            dbus_message_iter_recurse(&args, &subargs);
            strcat(ret, " [ ");
            while (dbus_message_iter_get_arg_type(&subargs)
                    != DBUS_TYPE_INVALID) {
                switch (dbus_message_iter_get_arg_type(&subargs)) {
                case DBUS_TYPE_STRING:
                    dbus_message_iter_get_basic(&subargs, &s);
                    bc = sprintf(s_msg, " %s", s);
                    strncat(ret, s_msg, bc+1);
                    break;
                case DBUS_TYPE_INT32:
                    dbus_message_iter_get_basic(&subargs, &i);
                    bc = sprintf(s_msg, " %d", i);
                    strncat(ret, s_msg, bc+1);
                    break;
                }
                dbus_message_iter_next(&subargs);
            }
            strcat(ret, " ] ");
        }
        dbus_message_iter_next(&args);
    }
    return ret;
}
char* _verbose_timeout(DBusTimeout *timeout) {
    char ret[1024] = "";
    sprintf(ret, "timeout: \n",
            (unsigned int)timeout, dbus_timeout_get_interval(timeout));
    return ret;        
}
/** -------------------------------------------------------*/
DBusHandlerResult handle_method_return(DBusConnection *conn,
        DBusMessage *reply) {
    struct seriallist_t *l = seriallist;
    while (l != NULL) {
        if (l->serial == dbus_message_get_reply_serial(reply)) {        
            printf("reply_msg:\t%s\n", _verbose_message(reply));
            return DBUS_HANDLER_RESULT_HANDLED;
        }
        l = l->next;
    }
    return DBUS_HANDLER_RESULT_HANDLED;
}
int reply_to_method_call(DBusMessage *msg, DBusConnection *conn) {
    DBusMessage *reply;
    DBusMessageIter args;
    DBusError err;
    // suppose we expect two argument, one is id, and second is
    // a string.
    if (!dbus_message_iter_init(msg, &args))
        err_quit("arg init error.\n");
    dbus_int32_t id;
    char *content;
    dbus_error_init( &err );
    dbus_message_get_args( msg, &err,
            DBUS_TYPE_INT32, &id,
            DBUS_TYPE_STRING, &content,
            DBUS_TYPE_INVALID );
    if (dbus_error_is_set(&err))
        err_quit("get arg error.\n");
    reply = dbus_message_new_method_return(msg);
    if (NULL == reply)
        err_quit("Memory is not enough.\n");
    printf("received call args: %d: %s\n", id, content);
    const char *comment = "reply to method call from com.redflag.csy.";
    dbus_message_iter_init_append( reply, &args );
    dbus_message_append_args ( reply,
            DBUS_TYPE_STRING, &comment,
            DBUS_TYPE_INVALID );
    dbus_uint32_t serial;
    dbus_connection_send( conn, reply, &serial );
    dbus_connection_flush( conn );
   
    printf( "build reply msg and send: \n\t%s\n", _verbose_message(reply) );
    dbus_message_unref( reply );
}
dbus_bool_t watchAddNotify(DBusWatch *watch, void *data) {
    struct watchlist_t *l;
    for (l = watchlist; l != NULL; l = l->next) {
        if (l->watch == watch)
            return TRUE;
    }
    printf("watchAdd: %s\n", _verbose_watch(watch));   
    l = dbus_new(struct watchlist_t, 1);
    if ( NULL == l )
        return FALSE;
    l->watch = watch;
    l->next = watchlist;
    watchlist = l;
    return TRUE;
}
void watchRemoveNotify(DBusWatch *watch, void *data) {
    struct watchlist_t *l, *pre;
    for ( pre = l = watchlist; l != NULL; pre = l, l = l->next ) {
        if (l->watch == watch) {
            printf("watchRemove: \n", dbus_watch_get_fd(watch));
            if ( l == watchlist ) {
                watchlist = l->next;
                dbus_free(l);
            } else {
                pre->next = l->next;
                dbus_free(l);
            }
            break;
        }
    }        
}
void watchToggleNotify(DBusWatch *watch, void *data) {
    if (watch == NULL)
        err_quit("line %d: watch should not be null.", __LINE__);
    printf( "toggleNotify: watch %d toogled %s",
            dbus_watch_get_fd(watch),
            dbus_watch_get_enabled(watch)?"enable":"disabled" );
}
/**
* process any watches added to connection
*/
dbus_bool_t watchHandler() {
    struct watchlist_t *l;
    fd_set rfds, wfds, efds;
    int maxid = -1, fd;
    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    FD_ZERO(&efds);
    // prepare all readble and writable fds
    for (l = watchlist; l != NULL; l = l->next) {
        if (!dbus_watch_get_enabled(l->watch))
            continue;
        fd = dbus_watch_get_fd(l->watch);
        if ( fd & DBUS_WATCH_READABLE ) {
            FD_SET(fd, &rfds);
            maxid = (maxid  fd? fd: maxid);
        }
        if ( fd & DBUS_WATCH_WRITABLE ) {
            FD_SET(fd, &wfds);
            maxid = (maxid  fd? fd: maxid);
        }
        if ( fd & DBUS_WATCH_ERROR ) {
            FD_SET(fd, &efds);
            maxid = (maxid  fd? fd: maxid);
        }
    }
    int ret = select(maxid+1, &rfds, &wfds, &efds, NULL);
    if (ret = 0)
        return;
   
    // call dbus_watch_handle is a must, it uses internal predefined
    // watch handler to do some thing, but i am not  quite sure what
    // it is right now.
    for (l = watchlist; l != NULL; l = l->next) {
        fd = dbus_watch_get_fd(l->watch);
   
        if (FD_ISSET(fd, &rfds))
            dbus_watch_handle(l->watch, DBUS_WATCH_READABLE);
         
        if (FD_ISSET(fd, &wfds))
            dbus_watch_handle(l->watch, DBUS_WATCH_WRITABLE);
        
        if (FD_ISSET(fd, &efds))
            dbus_watch_handle(l->watch, DBUS_WATCH_ERROR);   
    }
}
/**---- timeout process functions ------------------------------*/
dbus_bool_t timeoutAddNotify(DBusTimeout *timeout, void *data) {
    struct timeoutlist_t *l;
    for (l = timeoutlist; l != NULL; l = l->next) {
        if (l->timeout == timeout)
            return TRUE;
    }
    l = dbus_new(struct timeoutlist_t, 1);
    if (NULL == l)
        return FALSE;
    l->timeout = timeout;
    fprintf(stdout, "timeoutAdd:%s\n", _verbose_timeout(timeout));
    l->next = timeoutlist;
    timeoutlist = l;
    return TRUE;
}
void timeoutRemoveNotify(DBusTimeout *timeout, void *data) {
    struct timeoutlist_t *pre = NULL, *l = timeoutlist;
    while( l != NULL ) {
        if (l->timeout == timeout) {
            if (pre == NULL)
                timeoutlist = l->next;
            else
                pre->next = l->next;
            fprintf(stdout, "timeoutRemove:%s\n",
                    _verbose_timeout(timeout));
            break;
        }
        pre = l;
        l = l->next;
    }
}
void timeoutToggleNotify(DBusTimeout *timeout, void *data) {
    fprintf(stdout, "timeoutToggle: %s\n", _verbose_timeout(timeout));
}
/**
* in this function, we call dbus_timeout_handle to handle all timeout
* events, it will call internal predefined handler to process.
*/
void timeoutHandle() {
    struct timeoutlist_t *l = timeoutlist;
    for (; l != NULL; l = l->next) {
        if (dbus_timeout_get_enabled(l->timeout)) {
            printf("timeoutHandle: %s\n", _verbose_timeout(l->timeout));
            dbus_timeout_handle(l->timeout);
        }
    }
}
/**----------- all handlers -------------------------------------*/
/**
* filter messages that already stayed in the incoming queue,
* decide whether a further process is needed.
*/
DBusHandlerResult msgFilter(DBusConnection *conn,
        DBusMessage *msg, void *data) {
    printf("incoming msg: %s\n", _verbose_message(msg));
    switch (dbus_message_get_type(msg)) {
    case DBUS_MESSAGE_TYPE_METHOD_CALL:
        if (!strcmp(dbus_message_get_member(msg), "ignore")) {
            DBusMessage *errMsg;
            errMsg = dbus_message_new_error(msg,
                    "com.redflag.csy.IgnoreService",
                    "this demonstrate the filter.");
            dbus_connection_send(conn, errMsg, NULL);
            return DBUS_HANDLER_RESULT_HANDLED;
        } else
            break;
    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
        // never reach here.
        break;
    case DBUS_MESSAGE_TYPE_SIGNAL:
        break;
    case DBUS_MESSAGE_TYPE_ERROR:
        break;
    }
    // set this flag is very important, if not, dbus may not
    // process messages for you. it pass the control to dbus
    // default filter.
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
DBusHandlerResult subsection_com_handler(DBusConnection* conn,
        DBusMessage* msg, void* data) {
    if ( strncmp(dbus_message_get_path(msg), objectPaths[1],
                strlen(objectPaths[1])) != 0 ) {
        printf("subsection_com_handler: something wrong.\n");
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
    if ( strncmp(dbus_message_get_member(msg), "pseudo", 6) == 0 ) {
        reply_to_method_call(msg, conn);
        printf("subsection_com_handler: handled.\n");
        return DBUS_HANDLER_RESULT_HANDLED;
    } else
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
DBusHandlerResult subsection_org_freedesktop_handler(
        DBusConnection* conn, DBusMessage* msg, void* data) {
    if ( strncmp(dbus_message_get_path(msg), objectPaths[0],
                strlen(objectPaths[0])) != 0 ) {
        printf("subsection_org_freedesktop__handler: something wrong.\n");
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
   
    if ( strncmp(dbus_message_get_member(msg), "error", 5) == 0 ) {
        printf("subsection_org_freedesktop_handler(error): handled.\n");
        return DBUS_HANDLER_RESULT_HANDLED;
    } else
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
DBusHandlerResult subsection_com_redflag_handler(DBusConnection* conn,
        DBusMessage* msg, void* data) {
    if ( strncmp(dbus_message_get_path(msg), objectPaths[2],
                strlen(objectPaths[2])) != 0 ) {
        printf("subsection_com_redflag_handler: something wrong.\n");
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
   
    if ( strncmp(dbus_message_get_member(msg), "pseudo", 6) == 0 ) {
        reply_to_method_call(msg, conn);
        printf("subsection_com_redflag_handler: handled.\n");
        return DBUS_HANDLER_RESULT_HANDLED;
    } else
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
DBusHandlerResult object_dbus_handler(DBusConnection* conn,
        DBusMessage* msg, void* data) {
    if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
        printf("object_dbus_handler: method_return.\n");
        int ret = handle_method_return( conn, msg );
        printf("object_dbus_handler: handled.\n");
        return ret;
    }
    fprintf(stdout, "object_dbus_handler: cannot handle.\n");
    fprintf(stdout, "\t%s\n", _verbose_message(msg));
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
DBusHandlerResult object_csy_handler(DBusConnection* conn,
        DBusMessage* msg, void* data) {
    switch (dbus_message_get_type(msg)) {
    case DBUS_MESSAGE_TYPE_SIGNAL:
    case DBUS_MESSAGE_TYPE_ERROR:
        fprintf(stdout, "object_csy_handler(error/signal):\n\t%s\n",
                _verbose_message(msg));
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
            return handle_method_return(conn, msg);
    case DBUS_MESSAGE_TYPE_METHOD_CALL:
        if ( strstr(dbus_message_get_path(msg), "sycao") != NULL ) {
            printf("object_csy_handler(call): "
                    "cannot handle, through to tree.");
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        }
        if ( !strcmp(dbus_message_get_member(msg), "pseudo") ) {
            reply_to_method_call(msg, conn);
            printf("object_csy_handler(call): handled.\n");
            return DBUS_HANDLER_RESULT_HANDLED;
        } else {
            fprintf(stdout, "object_csy_handler(call): cannot handle.\n");
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        }
    }
}
void object_unregister_handler(DBusConnection* conn, void* data) {
    printf("object_unregister_handler:\n");
}
/**----------------testing routines ----------------------------------*/
/**
* test send signal method call, send certain signal randomly
*/
void send_random_signal(DBusConnection *conn) {
    DBusMessage *msg;
    char *msg_args[] = {
        "/org/freedesktop/DBus\0org.freedesktop.DBus\0NotExist",
        "/org/freedesktop/HAL\0org.freedesktop.HAL\0Device",
        "/com/redflag/csy\0com.redflag.csy\0NewSignal",
        "\0", "\0"
    };
    char *pargs = msg_args[rand()%(sizeof(msg_args)/sizeof(msg_args[0]))];
    if (!*pargs)
        return;
   
    long chance = 0x0fffffff;
    if ((rand() % chance) > 100)
        return;
    char *path = pargs;
    char *intf, *member;
    while( *pargs++ );
        intf = pargs;
    while( *pargs++ );
        member = pargs;
//    printf("%s,%s,%s\n", path, intf, member);
    dbus_uint32_t serial;
    msg = dbus_message_new_signal(path, intf, member);
    if (NULL == msg)
        err_quit("no enough memory.\n");
    if ( !dbus_connection_send(conn, msg, &serial) )
        fprintf( stderr, "no enough memory to send signal.\n" );
    fprintf(stdout, "SendSignal(%d): %s\n", serial, _verbose_message(msg));
}
void pendingCallNotify(DBusPendingCall *pending, void *data) {
    // one can process the pending and then read the reply message
    // alternatively, one can leave it to message handlers
    DBusMessage *msg = dbus_pending_call_steal_reply(pending);   
    printf( "pendingCallNotify: %s\n", _verbose_message(msg) );
}
void send_random_method_expecting_reply(DBusConnection *conn) {
    DBusMessage *msg;
    char *msg_args[] = {
        "org.freedesktop.DBus\0/org/freedesktop/DBus\0org.freedesktop.DBus\0ListNames",
        "org.freedesktop.DBus\0/org/freedesktop/DBus\0org.freedesktop.DBus.Peer\0Ping",
        "org.freedesktop.DBus\0/org/freedesktop/DBus\0org.freedesktop.DBus.Peer\0GetMachineId",
        "\0" // add possibility of not sending any msg this turn
    };
    long chance = 0x0fffffff;
    if ((rand() % chance) > 100)
        return;
    char *pargs = msg_args[rand()%(sizeof(msg_args)/sizeof(msg_args[0]))];
    if (!*pargs)
        return;   
    char *dest, *path, *intf, *member;
    dest = pargs;
    while( *pargs++ );
        path = pargs;
    while( *pargs++ );
        intf = pargs;
    while( *pargs++ );
        member = pargs;
   
    msg = dbus_message_new_method_call(dest, path, intf, member);
    if (NULL == msg)
        err_quit("no enough memory.\n");
    DBusPendingCall *pendingCall;
    if (!dbus_connection_send_with_reply(conn, msg, &pendingCall, 10000))
        fprintf( stderr, "no memory to send method_call.\n" );
    dbus_pending_call_set_notify(pendingCall, pendingCallNotify, NULL, NULL);
    struct seriallist_t *l;
    l = dbus_new(struct seriallist_t, 1);
    l->serial = dbus_message_get_serial(msg);
    l->next = seriallist;
    seriallist = l;
    fprintf(stdout, "SendMethod: %s\n", _verbose_message(msg));
}
int dbus_process_msg_loop() {
    DBusConnection *conn;
    DBusError *perr;
    // 1. connection to bus
    perr = dbus_new(DBusError, 1);
    dbus_error_init(perr);
    conn = dbus_bus_get(DBUS_BUS_SESSION, perr);
    if ( dbus_error_is_set(perr) )
        err_quit("connection failed.\n");
    // 2. request well-known name
    int ret = dbus_bus_request_name( conn, "com.redflag.csy",
            DBUS_NAME_FLAG_REPLACE_EXISTING, perr );
    if ( DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret )
        err_quit("not primary owner.\n");
    // 3. register any handler
    dbus_bus_add_match( conn,
            "type='method_call',path='/org/freedesktop/csy'"
            ",interface='com.redflag.sycao',member='faked'"
            , perr);
    if (dbus_error_is_set(perr))
        err_quit("add match failed.\n");
    dbus_connection_add_filter( conn, msgFilter, NULL, NULL);
    dbus_connection_set_watch_functions( conn,
            watchAddNotify, watchRemoveNotify, watchToggleNotify,
            NULL, NULL );
    dbus_connection_set_timeout_functions( conn,
            timeoutAddNotify, timeoutRemoveNotify, timeoutToggleNotify,
            NULL, NULL );
    int i;
    for (i = 0; i  sizeof(objectPaths)/sizeof(objectPaths[0]); i++) {
        if (i  3)
            dbus_connection_register_fallback( conn,
                    objectPaths, &objectPathVTable, NULL );
        else
            dbus_connection_register_object_path( conn,
                    objectPaths, &objectPathVTable, NULL);
    }
    printf("main: registered %d objectHandlers.\n", i);
    // 4. main loop: wait and process incoming msgs
    // there are several steps :
    //    a. check if any watch is ready for read (incoming data prepared)
    //    or write (outgoing data prepared), and process it.
    //    b. check if any timeout occurred ( i know now method_call that
    //    needs a reply will set a timeout ), and process it.
    //    c. call dispatch will do:
    //        i. parse incoming raw data if has.
    //        ii. process any pending call ( bind with a reply message );
    //        ii. call any filter registered.
    //        iv. call any object path handler registered.
    //        ps: a single dispatch call processes at most one message.
    //            
    while( 1 ) {
        DBusDispatchStatus status;
        
        while( 1 ) {
            watchHandler();
            timeoutHandle();
            status = dbus_connection_dispatch( conn );
            
            switch( status ) {
            case DBUS_DISPATCH_DATA_REMAINS:
                // there may be more msgs remain, go on
                printf("DBUS_DISPATCH_DATA_REMAINS\n");
                continue;
            case DBUS_DISPATCH_COMPLETE:
                break;
            case DBUS_DISPATCH_NEED_MEMORY:
                fprintf( stderr, "more memory is needed.\n" );
            }
            break;
        }
        send_random_signal( conn );
        send_random_method_expecting_reply( conn );
}
    dbus_free(perr);
    return 0;
}
int main(int argc, char **argv) {
    return dbus_process_msg_loop();
}
编译的时候带上:
CFLAGS=-Wall `pkg-config dbus-1 --cflags`
LDFLAGS=`pkg-config dbus-1 --libs`
可以用下面的脚本测试下不同的对象路径、接口和方法的影响:
#!/bin/bash
if [ $# == 0 ]; then
        loop=10
else
        loop=$1
fi
loop2=$loop
loop3=$loop
loop4=$loop
while (( loop > 0 ))
do
        dbus-send --session --type="method_call" --print-reply  --dest="com.redflag.csy" "/com/redflag/csy" "com.redflag.csy.pseudo" int32:$loop string:"hello,dbus1"
        let "loop = loop - 1"
done
while (( loop2 > 0 ))
do
        dbus-send --session --type="method_call" --print-reply  --dest="com.redflag.csy" "/org/freedesktop/csy" "com.redflag.csy.pseudo" int32:$loop2 string:"hello,dbus2"
        let "loop2 = loop2 - 1"
done
while (( loop3 > 0 ))
do
        dbus-send --session --type="method_call" --print-reply  --dest="com.redflag.csy" "/com/redflag/sycao" "com.redflag.sycao.pseudo" int32:$loop3 string:"hello,dbus3"
        let "loop3 = loop3 - 1"
done
while (( loop4 > 0 ))
do
        dbus-send --session --type="method_call" --print-reply  --dest="com.redflag.csy" "/org/freedesktop/csy" "com.redflag.csy.ignore" int32:$loop4 string:"hello,dbus4"
        let "loop4 = loop4 - 1"
done

Avatar_small
GTA 5 For Android AP 说:
2020年1月13日 17:55

Well, this is definitely an interesting post out there and I would like to know more about it. Let us know if we can include a little bit information about this on our website.

Avatar_small
Raymond Diggs 说:
2020年3月16日 13:20

The judge of the court is fully equipped for the advancement of the team. Implementation of the use of the best law essay writing service is flicked for humans. The turn is invited for the role. Manners are invited for humans. The chip is allowed for the mid of the paths for almoners for the fieldwork and its impact on the field.

Avatar_small
bestbudgetreport 说:
2020年6月17日 21:04

The best laptop under $500: Acer Aspire 5 · The best 14-inch laptop under $500: Acer Swift 3; The best 2-in-1 under $500: Microsoft Surface Go 2; The ... best laptops under 500

Avatar_small
토토사이트 说:
2020年6月28日 04:18

I’d must seek advice from you here. Which is not some thing Which i do! I enjoy reading an article that may make people feel. Also, thanks for allowing me to comment!

Avatar_small
Mobile car service 说:
2020年6月28日 05:13

I like the helpful information you provide in your articles. I will bookmark your blog and check again here regularly. I am quite certain I will learn a lot of new stuff right here! Best of luck for the next!

Avatar_small
harga ban loader 说:
2020年6月28日 05:15

It is rather grateful for the help in this question, can, I too can help you something?

Avatar_small
Dekorasi ulang tahun 说:
2020年7月01日 19:37

When I originally commented I clicked the -Notify me when new comments are added- checkbox now whenever a comment is added I receive four emails sticking with the same comment. Possibly there is any way you can get rid of me from that service? Thanks!

Avatar_small
cara mengetahui pass 说:
2020年7月01日 19:37

great list…i’ve had a lot of those bookmarked for inspiration.

Avatar_small
청주출장마사지 说:
2020年7月06日 20:43

Can I just now say such a relief to discover one who truly knows what theyre dealing with on-line. You actually know how to bring a concern to light and earn it important. Lots more people have to look at this and see why side of the story. I cant think youre not more popular because you certainly develop the gift.

Avatar_small
우리카지노 说:
2020年7月06日 20:46

very nice post, i surely love this web site, persist in it

Avatar_small
코인카지노 说:
2020年7月07日 14:27

This is a great blog. and i want to visit this every day of the week , 

Avatar_small
irrigation Company i 说:
2020年9月28日 15:23

Took me time to understand all of the comments, but I seriously enjoyed the write-up. It proved being really helpful to me and Im positive to all of the commenters right here! Its constantly nice when you can not only be informed, but also entertained! I am certain you had enjoyable writing this write-up.

Avatar_small
swimming pool contra 说:
2020年10月04日 15:53

I quite like reading an article that can make people think. Also, thanks for allowing for me to comment!

Avatar_small
lsm99 说:
2020年10月05日 21:09

Good to become visiting your weblog again, it has been months for me. Nicely this article that i've been waited for so long. I will need this post to total my assignment in the college, and it has exact same topic together with your write-up. Thanks, good share.

Avatar_small
Arianna 说:
2020年10月07日 18:28

This is also a very good post which I really enjoy reading. It is not everyday that I have the possibility to see something like this.   carpet shop uae

Avatar_small
arianna 说:
2020年10月09日 20:10

Really nice and interesting post. I was looking for this kind of information and enjoyed reading this one.   gloves supplier Dubai

Avatar_small
arianna 说:
2020年10月11日 01:56

Very nice article, I enjoyed reading your post, very nice share, I want to twit this to my followers. Thanks!.   Media Agencies in Dubai

Avatar_small
Arianna 说:
2020年10月14日 03:17

This is really very nice post you shared, i like the post, thanks for sharing..  budapest student accommodation

Avatar_small
arianna 说:
2020年10月14日 17:56

I feel very grateful that I read this. It is very helpful and very informative and I really learned a lot from it.   ทำแบรนด์สบู่

Avatar_small
Arianna 说:
2020年10月17日 01:28

The writer is enthusiastic about purchasing wooden furniture on the web and his exploration about best wooden furniture has brought about the arrangement of this article.   writers

Avatar_small
Arianna 说:
2020年10月17日 21:20

This is a fantastic website , thanks for sharing.   Relationship Counselling

Avatar_small
Arianna 说:
2020年10月18日 18:43

It is extremely nice to see the greatest details presented in an easy and understanding manner.   Halloween candy gift baskets

Avatar_small
Arianna 说:
2020年10月19日 16:04

The material and aggregation is excellent and telltale as comfortably.   interest rate formula

Avatar_small
Arianna 说:
2020年10月23日 00:54

Nice blog. Found this while searching through   Youtube reseller panel

Avatar_small
Arianna 说:
2020年10月23日 15:16

Glad to chat your blog, I seem to be forward to more reliable articles and I think we all wish to thank so many good articles, blog to share with us.    buy cheap instagram followers

Avatar_small
Jacob 说:
2021年9月30日 14:07

If you don"t mind proceed with this extraordinary work and I anticipate a greater amount of your magnificent blog entries stamping cable protector

Avatar_small
COOK 说:
2022年1月24日 16:46

Thanks for the blog filled with so many information. Stopping by your blog helped me to get what I was looking for. Now my task has become as easy as ABC. 토토커뮤니티

Avatar_small
. 카지노사이트 说:
2022年3月14日 03:36

It is a fantastic post – immense clear and easy to understand. I am also holding out for the sharks too that made me laugh. retrogames cc pokemon

Avatar_small
. 카지노사이트 说:
2022年4月08日 03:29

You delivered such an impressive piece to read, giving every subject enlightenment for us to gain information. Thanks for sharing such information with us due to which my several concepts have been cleared. dpboss

Avatar_small
. 카지노사이트 说:
2022年5月13日 20:44

Great things you’ve always shared with us. Just keep writing this kind of posts.The time which was wasted in traveling for tuition now it can be used for studies.Thanks zccct inserts

Avatar_small
laimconnor 说:
2022年5月28日 14:45

A debt of gratitude is in order for sharing this data. I truly like your blog entry definitely. You have truly shared an enlightening and fascinating blog entry with individuals.. mitsubishi ac dubai

Avatar_small
laimconnor 说:
2022年5月31日 18:53

The site is affectionately adjusted and spared as much as date. So it ought to be, a debt of gratitude is in order for imparting this to us. movers

Avatar_small
laimconnor 说:
2022年6月03日 18:05

I was exceptionally dazzled by this post, this site has consistently been charming news Thank you especially for such a fascinating post, and I meet them all the more frequently then I visited this site. create an nft

Avatar_small
topseom114 说:
2022年6月14日 10:10

I have really enjoyed reading your blog posts. Any way I'll be subscribing to your feed and I hope you post again soon. Big thanks for the useful info. 바카라사이트

Avatar_small
. 카지노사이트 说:
2022年7月02日 02:37

Cool stuff you have got and you keep update all of us. hythm sportschool Den Haag

Avatar_small
dark web/deep web/d 说:
2022年8月04日 18:56

The JavaScript that hides these links is part of the programming that most web browsers are programmed to run. However, some advanced JavaScript hackers have discovered ways to bypass JavaScript codes and access the Dark Web.  dark web links

Avatar_small
dark web/deep web/d 说:
2022年8月04日 19:40

Some sites allow you to browse their Dark Web links for free. While it is possible to find many of these websites online, they are generally not worth the time or effort it takes to investigate them.   deep web

Avatar_small
dark web/deep web/d 说:
2022年8月04日 19:55

While using search engines to discover Bangla links can be effective, it is recommended that you also expose yourself to the world of the Dark Web in order to gain access to the many interesting, informative, and entertaining web sites that can help you stay ahead of the trends on the Internet.  dark web links

Avatar_small
dark web/deep web/d 说:
2022年8月04日 20:17

All this activity is a huge boon to the hackers and scammers out there who wish to get your personal information. The darker the links to the website, the more valuable the information is to them.   dark web sites

Avatar_small
dark web/deep web/d 说:
2022年8月04日 20:32

As with anything else on the internet, people will always be willing to try new ways to get rich. So why not try your hand at making a bit of extra money? There is a lot of room here to make a living, and the benefits of Dark Web links are plenty.  dark web

Avatar_small
dark web/deep web/d 说:
2022年8月04日 20:48

Most of the other things that he teaches you in his real affiliate marketing success stories program are extremely valuable. They include finding good advertising sources, choosing the best products to promote, writing good sales copy, and more.   work from home jobs

Avatar_small
dark web/deep web/d 说:
2022年8月04日 21:05

If you have your own product, be sure to incorporate a weight-loss component into it. It can be as simple as a free eBook or a complete program like Head Starts.   affiliate marketing success

Avatar_small
. 카지노사이트 说:
2022年8月16日 02:10

Thank you so much for the post you do. I like your post and all you share with us is up to date and quite informative, i would like to bookmark the page so i can come here again to read you, as you have done a wonderful job. pullman residence condo

Avatar_small
. 카지노사이트 说:
2022年8月17日 01:15

Thanks for the blog filled with so many information. Stopping by your blog helped me to get what I was looking for. Now my task has become as easy as ABC. pullman residence

Avatar_small
. 카지노사이트 说:
2022年8月18日 01:53

I admire what you have done here. I like the part where you say you are doing this to give back but I would assume by all the comments that this is working for you as well. onewalmart login

Avatar_small
. 카지노사이트 说:
2022年8月24日 03:01

Nice post. I was checking constantly this blog and I am impressed! Extremely helpful information specially the last part I care for such info a lot. I was seeking this particular information for a very long time. Thank you and good luck. Httpmarketing de Google experts volgen dagelijks de laatste Google trends

Avatar_small
. 카지노사이트 说:
2022年8月29日 02:36

I recently came across your blog and have been reading along. I thought I would leave my first comment. I don’t know what to say except that I have enjoyed reading. instagram-pva-accounts

Avatar_small
chacha 说:
2022年9月19日 10:52

This particular is usually apparently essential and moreover outstanding truth along with for sure fair-minded and moreover admittedly useful My business is looking to find in advance designed for this specific useful stuffs
<a href="https://www.nomukti.com/" rel="nofollow">토토검증사이트</a><br>

Avatar_small
PAPA 说:
2022年9月19日 10:52

This particular is usually apparently essential and moreover outstanding truth along with for sure fair-minded and moreover admittedly useful My business is looking to find in advance designed for this specific useful stuffs
<a href="https://mtamsal.com/" rel="nofollow">토토검증사이트</a><br>

Avatar_small
PHG011 说:
2022年9月19日 10:53

Most of the time I don’t make comments on websites, but I'd like to say that this article really forced me to do so.
<a href="https://www.nomukti.com/" target="_blank" title="토토검순위">토토검증소</a>

Avatar_small
blackhole 说:
2022年9月19日 10:53

Most of the time I don’t make comments on websites, but I'd like to say that this article really forced me to do so.
<a href="https://mtamsal.com/" target="_blank" title="토토검증소">토토검증순위</a>


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter