rpc.c File Reference

This file implements rpc calls from one application to another. More...

#include "internal.h"
#include <assert.h>
#include <stdlib.h>
Include dependency graph for rpc.c:

Go to the source code of this file.

Defines

#define UNUSED(x)   (void)(x)

Functions

void _parse_id (const char *id, eripc_bus_t *bus, char *sender, int *serial)
void _make_id (eripc_bus_t bus, const char *sender, int serial, char *id)
static eripc_error_t _append_args (DBusMessage *msg, int type, va_list var_args)
eripc_error_t eripc_get_timeout (eripc_context_t *context, int *timeout)
void * eripc_get_system_connection (eripc_context_t *context)
void * eripc_get_session_connection (eripc_context_t *context)
eripc_error_t eripc_set_timeout (eripc_context_t *context, int timeout)
static void eripc_reply_handler (osso_context_t *osso, DBusMessage *msg, _osso_callback_data_t *cb_data, eripc_bus_t dbus_type)
static eripc_error_t _send_signal_helper (eripc_context_t *context, eripc_bus_t bus_type, const char *signal_path, const char *signal_interface, const char *signal_name, eripc_data_t arg_type, va_list va_args)
eripc_error_t eripc_send_signal_varargs (eripc_context_t *context, eripc_bus_t bus_type, const char *signal_path, const char *signal_interface, const char *signal_name, eripc_data_t arg_type,...)
eripc_error_t eripc_send_signal (eripc_context_t *context, eripc_bus_t bus_type, const char *signal_name, const char *argument)
static eripc_error_t _send_helper (eripc_context_t *context, eripc_handler_t *reply_handler, const void *user_data, eripc_bus_t bus_type, const char *destination, const char *message_name, eripc_data_t arg_type, va_list va_args)
static eripc_error_t _send_sync_helper (eripc_context_t *context, eripc_event_info_t **reply, eripc_bus_t bus_type, const char *destination, const char *message_name, eripc_data_t arg_type, va_list va_args)
eripc_error_t eripc_send_varargs (eripc_context_t *context, eripc_handler_t *reply_handler, const void *user_data, eripc_bus_t bus_type, const char *destination, const char *message_name, eripc_data_t arg_type,...)
eripc_error_t eripc_send_varargs_and_wait (eripc_context_t *context, eripc_event_info_t **reply, eripc_bus_t bus_type, const char *destination, const char *message_name, eripc_data_t arg_type,...)
eripc_error_t eripc_send_string_and_wait (eripc_context_t *context, eripc_event_info_t **reply, eripc_bus_t bus_type, const char *destination, const char *message_name, const char *string_to_send)
eripc_error_t eripc_send_int_and_wait (eripc_context_t *context, eripc_event_info_t **reply, eripc_bus_t bus_type, const char *destination, const char *message_name, int value_to_send)
eripc_error_t eripc_send_bool_and_wait (eripc_context_t *context, eripc_event_info_t **reply, eripc_bus_t bus_type, const char *destination, const char *message_name, gboolean value_to_send)
eripc_error_t eripc_send_string (eripc_context_t *context, eripc_handler_t *reply_handler, const void *user_data, eripc_bus_t bus_type, const char *destination, const char *message_name, const char *string_to_send)
eripc_error_t eripc_send_int (eripc_context_t *context, eripc_handler_t *reply_handler, const void *user_data, eripc_bus_t bus_type, const char *destination, const char *message_name, int value_to_send)
eripc_error_t eripc_send_bool (eripc_context_t *context, eripc_handler_t *reply_handler, const void *user_data, eripc_bus_t bus_type, const char *destination, const char *message_name, gboolean value_to_send)
eripc_error_t eripc_event_info_free (eripc_context_t *context, eripc_event_info_t *info)
static eripc_error_t _reply_helper (eripc_context_t *context, const char *message_id, eripc_data_t arg_type, va_list va_args)
eripc_error_t eripc_reply_varargs (eripc_context_t *context, const char *message_id, eripc_data_t arg_type,...)
eripc_error_t eripc_reply_string (eripc_context_t *context, const char *message_id, const char *string)
eripc_error_t eripc_reply_int (eripc_context_t *context, const char *message_id, int value)
eripc_error_t eripc_reply_bool (eripc_context_t *context, const char *message_id, gboolean value)
eripc_error_t eripc_reply_error (eripc_context_t *context, const char *message_id, const char *name, const char *message)

Detailed Description

This file implements rpc calls from one application to another.

Definition in file rpc.c.


Define Documentation

#define UNUSED (  )     (void)(x)

Copyright (C) 2008 iRex Technologies B.V. All rights reserved.

Based on code found in libosso library by Kimmo Hämäläinen <kimmo.hamalainen@nokia.com>

Definition at line 34 of file rpc.c.


Function Documentation

static eripc_error_t _append_args ( DBusMessage *  msg,
int  type,
va_list  var_args 
) [static]

Definition at line 75 of file rpc.c.

References ERIPC_ERROR, ERIPC_ERROR_INVALID, ERIPC_ERROR_SUCCESS, ERIPC_TYPE_BOOL, ERIPC_TYPE_BYTE, ERIPC_TYPE_DATA, ERIPC_TYPE_DOUBLE, ERIPC_TYPE_INT, ERIPC_TYPE_INVALID, ERIPC_TYPE_STRING, ERIPC_TYPE_UINT, and ULOG_ERR_F.

Referenced by _reply_helper(), _send_helper(), _send_signal_helper(), and _send_sync_helper().

00077 {
00078     eripc_error_t rc = ERIPC_ERROR_SUCCESS;
00079 
00080     while (type != ERIPC_TYPE_INVALID && rc == ERIPC_ERROR_SUCCESS) {
00081         dbus_bool_t ret;
00082         char *s;
00083         const char *empty_str = "";
00084         int i;
00085         unsigned int u;
00086         double d;
00087 
00088         switch (type) {
00089         case ERIPC_TYPE_BOOL:
00090             i = va_arg(var_args, int);
00091             ret = dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN,
00092                                      &i, DBUS_TYPE_INVALID);
00093             if (!ret) rc = ERIPC_ERROR;
00094             break;
00095         case ERIPC_TYPE_BYTE:
00096             i = va_arg(var_args, int);
00097             ret = dbus_message_append_args(msg, DBUS_TYPE_BYTE,
00098                                      &i, DBUS_TYPE_INVALID);
00099             if (!ret) rc = ERIPC_ERROR;
00100             break;
00101         case ERIPC_TYPE_INT:
00102             i = va_arg(var_args, int);
00103             ret = dbus_message_append_args(msg, DBUS_TYPE_INT32,
00104                                      &i, DBUS_TYPE_INVALID);
00105             if (!ret) rc = ERIPC_ERROR;
00106             break;
00107         case ERIPC_TYPE_UINT:
00108             u = va_arg(var_args, unsigned int);
00109             ret = dbus_message_append_args(msg, DBUS_TYPE_UINT32,
00110                                      &u, DBUS_TYPE_INVALID);
00111             if (!ret) rc = ERIPC_ERROR;
00112             break;
00113         case ERIPC_TYPE_DOUBLE:
00114             d = va_arg(var_args, double);
00115             ret = dbus_message_append_args(msg, DBUS_TYPE_DOUBLE,
00116                                      &d, DBUS_TYPE_INVALID);
00117             if (!ret) rc = ERIPC_ERROR;
00118             break;
00119         case ERIPC_TYPE_STRING:
00120             s = va_arg(var_args, char *);
00121             if (s == NULL) {
00122                 ret = dbus_message_append_args(msg,
00123                     DBUS_TYPE_STRING, &empty_str,
00124                     DBUS_TYPE_INVALID);
00125             } else {
00126                 ret = dbus_message_append_args(msg,
00127                     DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID);
00128             }
00129             if (!ret) rc = ERIPC_ERROR;
00130             break;
00131         case ERIPC_TYPE_DATA:
00132             i = va_arg(var_args, int); /* length of the data */
00133             s = va_arg(var_args, char *);
00134             ret = dbus_message_append_args(msg,
00135                       DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
00136                       &s, i, DBUS_TYPE_INVALID);
00137             if (!ret) rc = ERIPC_ERROR;
00138             break;
00139         default:
00140             ULOG_ERR_F("unknown type %d", type);
00141             rc = ERIPC_ERROR_INVALID;
00142             break;       
00143         }
00144         type = va_arg(var_args, int);
00145     }
00146     return rc;
00147 }

Here is the caller graph for this function:

void _make_id ( eripc_bus_t  bus,
const char *  sender,
int  serial,
char *  id 
)

Definition at line 70 of file rpc.c.

References MAX_MSGID_LEN.

Referenced by _send_sync_helper(), eripc_reply_handler(), and generic_signal_handler().

00071 {
00072     snprintf(id, MAX_MSGID_LEN, "%d,%s,%d", bus, sender, serial);
00073 }

Here is the caller graph for this function:

void _parse_id ( const char *  id,
eripc_bus_t bus,
char *  sender,
int *  serial 
)

Definition at line 37 of file rpc.c.

References MAX_SVC_LEN.

Referenced by _reply_helper(), and eripc_reply_error().

00039 {
00040     int i;
00041     char buf[20], *p;
00042 
00043     /* get bus type */
00044     for (i = 0, p = (char*) id; *p != ','; ++p, ++i) {
00045         assert(*p != '\0');
00046         assert(i < 20);
00047         buf[i] = *p;
00048     }
00049     buf[i] = '\0';
00050     *bus = atoi(buf);
00051     /* get sender */
00052     ++p;
00053     for (i = 0; *p != ','; ++p, ++i) {
00054         assert(*p != '\0');
00055         assert(i <= MAX_SVC_LEN);
00056         sender[i] = *p;
00057     }
00058     sender[i] = '\0';
00059     /* get serial */
00060     ++p;
00061     for (i = 0; *p != '\0'; ++p, ++i) {
00062         assert(i < 20);
00063         buf[i] = *p;
00064     }
00065     buf[i] = '\0';
00066     *serial = atoi(buf);
00067 }

Here is the caller graph for this function:

static eripc_error_t _reply_helper ( eripc_context_t context,
const char *  message_id,
eripc_data_t  arg_type,
va_list  va_args 
) [static]

Definition at line 763 of file rpc.c.

References _append_args(), _parse_id(), _eripc_context_t::conn, ERIPC_BUS_SESSION, ERIPC_BUS_SYSTEM, ERIPC_ERROR, ERIPC_ERROR_INVALID, ERIPC_ERROR_OOM, ERIPC_ERROR_SUCCESS, ERIPC_TYPE_INVALID, MAX_SVC_LEN, _eripc_context_t::reply_dummy, sender, serial, _eripc_context_t::sys_conn, and ULOG_ERR_F.

Referenced by eripc_reply_varargs().

00766 {
00767     DBusConnection *conn;
00768     DBusMessage *reply;
00769     char sender[MAX_SVC_LEN + 1];
00770     int serial;
00771     eripc_bus_t bus_type;
00772 
00773     if (context == NULL || message_id == NULL) {
00774         return ERIPC_ERROR_INVALID;
00775     }
00776     if (context->reply_dummy == NULL) {
00777         /* OOM has happened earlier in the handler, or
00778          * the context is invalid */
00779         ULOG_ERR_F("reply_dummy has not been created");
00780         return ERIPC_ERROR;
00781     }
00782 
00783     _parse_id(message_id, &bus_type, sender, &serial);
00784     assert(bus_type == ERIPC_BUS_SYSTEM || bus_type == ERIPC_BUS_SESSION);
00785 
00786     if (bus_type == ERIPC_BUS_SYSTEM) {
00787         conn = context->sys_conn;
00788     } else {
00789         conn = context->conn;
00790     }
00791     if (!dbus_connection_get_is_connected(conn)) {
00792         ULOG_ERR_F("connection %p is not open", conn);
00793         return ERIPC_ERROR_INVALID;
00794     }
00795 
00796     /* make a copy of the reply_dummy and modify the copy */
00797     reply = dbus_message_copy(context->reply_dummy);
00798     if (reply == NULL) {
00799         ULOG_ERR_F("dbus_message_copy failed");
00800         return ERIPC_ERROR_OOM;
00801     }
00802     if (!dbus_message_set_destination(reply, sender)) {
00803         ULOG_ERR_F("dbus_message_set_destination failed");
00804         goto unref_and_exit;
00805     }
00806     if (!dbus_message_set_reply_serial(reply, serial)) {
00807         ULOG_ERR_F("dbus_message_set_reply_serial failed");
00808         goto unref_and_exit;
00809     }
00810 
00811     if (arg_type != ERIPC_TYPE_INVALID) {
00812         eripc_error_t rc;
00813         rc = _append_args(reply, arg_type, va_args);
00814         if (rc != ERIPC_ERROR_SUCCESS) {
00815             ULOG_ERR_F("dbus_message_append_args failed");
00816             goto unref_and_exit;
00817         }
00818     }
00819     
00820     if (!dbus_connection_send(conn, reply, NULL)) {
00821         ULOG_ERR_F("dbus_connection_send failed");
00822         goto unref_and_exit;
00823     }
00824     dbus_message_unref(reply);
00825     return ERIPC_ERROR_SUCCESS;
00826 
00827 unref_and_exit:
00828     dbus_message_unref(reply);
00829     return ERIPC_ERROR_OOM;
00830 }

Here is the call graph for this function:

Here is the caller graph for this function:

static eripc_error_t _send_helper ( eripc_context_t context,
eripc_handler_t reply_handler,
const void *  user_data,
eripc_bus_t  bus_type,
const char *  destination,
const char *  message_name,
eripc_data_t  arg_type,
va_list  va_args 
) [static]

Definition at line 352 of file rpc.c.

References _append_args(), _osso_callback_data_t::bus_type, _eripc_context_t::conn, _osso_callback_data_t::data, ERIPC_BUS_SESSION, ERIPC_BUS_SYSTEM, ERIPC_ERROR, ERIPC_ERROR_INVALID, ERIPC_ERROR_OOM, ERIPC_ERROR_SUCCESS, ERIPC_MEMBER_MATCH_ALL, ERIPC_PATH_MATCH_ALL, eripc_reply_handler(), ERIPC_TYPE_INVALID, _osso_callback_data_t::event_type, handler_id, _osso_callback_data_t::interface, interface, _osso_callback_data_t::match_rule, MAX_IF_LEN, MAX_OP_LEN, MAX_SVC_LEN, _osso_callback_data_t::message_id, msg, _osso_callback_data_t::name, _eripc_context_t::next_handler_id, _osso_callback_data_t::path, path, _osso_callback_data_t::service, service, _eripc_context_t::sys_conn, ULOG_ERR_F, _osso_callback_data_t::user_cb, and _osso_callback_data_t::user_data.

Referenced by eripc_send_varargs().

00359 {
00360     char service[MAX_SVC_LEN + 1], path[MAX_OP_LEN + 1],
00361          interface[MAX_IF_LEN + 1];
00362     _osso_callback_data_t *cb_data;
00363     DBusMessage *msg;
00364     DBusConnection *conn;
00365     unsigned int msg_serial = 0;
00366     int handler_id;
00367 
00368     if (context == NULL) {
00369         ULOG_ERR_F("context error");
00370         return ERIPC_ERROR_INVALID;
00371     }
00372 
00373     if (destination == NULL || message_name == NULL || destination[0] == '\0') {
00374         ULOG_ERR_F("destination and message_name must be provided");
00375         return ERIPC_ERROR_INVALID;
00376     }
00377 
00378     if (bus_type != ERIPC_BUS_SESSION && bus_type != ERIPC_BUS_SYSTEM) {
00379         ULOG_ERR_F("bus_type must be either ERIPC_BUS_SESSION "
00380                    "or ERIPC_BUS_SYSTEM");
00381         return ERIPC_ERROR_INVALID;
00382     }
00383 
00384     if (reply_handler == NULL && user_data != NULL) {
00385         ULOG_ERR_F("reply_handler == NULL: ignoring user_data "
00386                     "argument");
00387         fprintf(stderr, "Warning: reply_handler is NULL: ignoring"
00388                 " user_data argument");
00389     }
00390 
00391     if (bus_type == ERIPC_BUS_SESSION) {
00392         conn = context->conn;
00393     } else {
00394         conn = context->sys_conn;
00395     }
00396 
00397     if (!dbus_connection_get_is_connected(conn)) {
00398         ULOG_ERR_F("connection %p is not open", conn);
00399         return ERIPC_ERROR_INVALID;
00400     }
00401 
00402     make_default_service(destination, service);
00403     make_default_object_path(destination, path);
00404     make_default_interface(destination, interface);
00405 
00406     msg = dbus_message_new_method_call(service, path, interface,
00407                                        message_name);
00408     if (msg == NULL) {
00409         ULOG_ERR_F("dbus_message_new_method_call failed");
00410         goto _send_oom;
00411     }
00412 
00413     if (arg_type != ERIPC_TYPE_INVALID) {
00414         eripc_error_t rc;
00415         rc = _append_args(msg, arg_type, va_args);
00416         if (rc != ERIPC_ERROR_SUCCESS) {
00417             ULOG_ERR_F("invalid type");
00418             dbus_message_unref(msg);
00419             return rc;
00420         }
00421     }
00422 
00423     if (reply_handler == NULL) {
00424         dbus_message_set_no_reply(msg, TRUE);
00425     }
00426 
00427     if (!dbus_connection_send(conn, msg, &msg_serial)) {
00428         ULOG_ERR_F("dbus_connection_send failed");
00429         dbus_message_unref(msg);
00430         goto _send_oom;
00431     }
00432     dbus_message_unref(msg);
00433 
00434     if (reply_handler == NULL) {
00435         /* the caller does not want to handle the reply, so
00436          * let's not put any handler for it */
00437         return ERIPC_ERROR_SUCCESS;
00438     }
00439 
00440     cb_data = calloc(1, sizeof(_osso_callback_data_t));
00441     if (cb_data == NULL) {
00442         ULOG_ERR_F("calloc failed");
00443         goto _send_oom;
00444     }
00445     /* this is used to recognise the reply for this message */
00446     cb_data->message_id = (long)msg_serial;
00447 
00448     cb_data->user_cb = reply_handler;
00449     cb_data->user_data = (void*) user_data;
00450     cb_data->match_rule = NULL;
00451     cb_data->event_type = 0;
00452     cb_data->bus_type = bus_type;
00453     cb_data->data = context;
00454 
00455     cb_data->service = NULL;
00456     cb_data->path = ERIPC_PATH_MATCH_ALL;
00457     cb_data->interface = NULL;
00458     cb_data->name = ERIPC_MEMBER_MATCH_ALL;
00459 
00460     /* (eripc_filter removes the handler, otherwise this would need
00461      * to be saved somewhere) */
00462     handler_id = context->next_handler_id++;
00463 
00464     if (_eripc_set_handler((_eripc_context_t*)context,
00465                            eripc_reply_handler, cb_data, handler_id,
00466                            FALSE)) {
00467         return ERIPC_ERROR_SUCCESS;
00468     } else {
00469         ULOG_ERR_F("_set_handler failed");
00470         free(cb_data);
00471         return ERIPC_ERROR;
00472     }
00473 
00474 _send_oom:
00475 
00476     return ERIPC_ERROR_OOM;
00477 }

Here is the call graph for this function:

Here is the caller graph for this function:

static eripc_error_t _send_signal_helper ( eripc_context_t context,
eripc_bus_t  bus_type,
const char *  signal_path,
const char *  signal_interface,
const char *  signal_name,
eripc_data_t  arg_type,
va_list  va_args 
) [static]

Definition at line 252 of file rpc.c.

References _append_args(), _eripc_context_t::conn, ERIPC_BUS_SESSION, ERIPC_BUS_SYSTEM, ERIPC_ERROR, ERIPC_ERROR_INVALID, ERIPC_ERROR_OOM, ERIPC_ERROR_SUCCESS, ERIPC_TYPE_INVALID, msg, _eripc_context_t::sys_conn, and ULOG_ERR_F.

Referenced by eripc_send_signal_varargs().

00258 {
00259     DBusConnection *conn;
00260     DBusMessage *msg;
00261 
00262     if (context == NULL || signal_name == NULL) {
00263         return ERIPC_ERROR_INVALID;
00264     }
00265     
00266     if (bus_type != ERIPC_BUS_SESSION && bus_type != ERIPC_BUS_SYSTEM) {
00267         ULOG_ERR_F("bus_type must be either ERIPC_BUS_SESSION "
00268                    "or ERIPC_BUS_SYSTEM");
00269         return ERIPC_ERROR_INVALID;
00270     }
00271 
00272     if (bus_type == ERIPC_BUS_SESSION) {
00273         conn = context->conn;
00274     } else {
00275         conn = context->sys_conn;
00276     }
00277 
00278     if (!dbus_connection_get_is_connected(conn)) {
00279         ULOG_ERR_F("connection %p is not open", conn);
00280         return ERIPC_ERROR_INVALID;
00281     }
00282 
00283     msg = dbus_message_new_signal(signal_path, signal_interface, signal_name);
00284     if (msg == NULL) {
00285         ULOG_ERR_F("dbus_message_new_signal failed");
00286         return ERIPC_ERROR_OOM;
00287     }
00288 
00289     if (arg_type != ERIPC_TYPE_INVALID) {
00290         eripc_error_t rc;
00291         rc = _append_args(msg, arg_type, va_args);
00292         if (rc != ERIPC_ERROR_SUCCESS) {
00293             ULOG_ERR_F("dbus_message_append_args failed");
00294             dbus_message_unref(msg);
00295             return ERIPC_ERROR;
00296         }
00297     }
00298     
00299     if (!dbus_connection_send(conn, msg, NULL)) {
00300         ULOG_ERR_F("dbus_connection_send failed");
00301         dbus_message_unref(msg);
00302         return ERIPC_ERROR_OOM;
00303     }
00304     dbus_message_unref(msg);
00305 
00306     return ERIPC_ERROR_SUCCESS;
00307 }

Here is the call graph for this function:

Here is the caller graph for this function:

static eripc_error_t _send_sync_helper ( eripc_context_t context,
eripc_event_info_t **  reply,
eripc_bus_t  bus_type,
const char *  destination,
const char *  message_name,
eripc_data_t  arg_type,
va_list  va_args 
) [static]

Definition at line 481 of file rpc.c.

References _append_args(), _get_args(), _make_id(), eripc_event_info_t::args, eripc_event_info_t::bus_type, _eripc_context_t::conn, eripc_event_info_t::dbus_message, ERIPC_BUS_SESSION, ERIPC_BUS_SYSTEM, ERIPC_ERROR_INVALID, ERIPC_ERROR_OOM, ERIPC_ERROR_SUCCESS, ERIPC_ERROR_TIMEOUT, ERIPC_TYPE_INVALID, eripc_event_info_t::error, eripc_event_info_t::event_type, eripc_event_info_t::interface, interface, MAX_IF_LEN, MAX_MSGID_LEN, MAX_OP_LEN, MAX_SVC_LEN, eripc_event_info_t::message_id, msg, eripc_event_info_t::name, eripc_event_info_t::path, path, eripc_event_info_t::service, service, _eripc_context_t::sys_conn, _eripc_context_t::timeout_ms, and ULOG_ERR_F.

Referenced by eripc_send_varargs_and_wait().

00487 {
00488     char service[MAX_SVC_LEN + 1], path[MAX_OP_LEN + 1],
00489          interface[MAX_IF_LEN + 1];
00490     DBusMessage *msg;
00491     DBusMessage *reply_msg;
00492     DBusConnection *conn;
00493     DBusMessageIter iter;
00494     DBusError error;
00495     
00496     char id_buf[MAX_MSGID_LEN + 1];
00497 
00498     if (reply != NULL && *reply != NULL) {
00499          *reply = NULL;
00500    }
00501 
00502     if (context == NULL) {
00503         ULOG_ERR_F("context error");
00504         return ERIPC_ERROR_INVALID;
00505     }
00506 
00507     if (destination == NULL || message_name == NULL || destination[0] == '\0') {
00508         ULOG_ERR_F("destination and message_name must be provided");
00509         return ERIPC_ERROR_INVALID;
00510     }
00511 
00512     if (bus_type != ERIPC_BUS_SESSION && bus_type != ERIPC_BUS_SYSTEM) {
00513         ULOG_ERR_F("bus_type must be either ERIPC_BUS_SESSION "
00514                    "or ERIPC_BUS_SYSTEM");
00515         return ERIPC_ERROR_INVALID;
00516     }
00517 
00518     if (bus_type == ERIPC_BUS_SESSION) {
00519         conn = context->conn;
00520     } else {
00521         conn = context->sys_conn;
00522     }
00523 
00524     if (!dbus_connection_get_is_connected(conn)) {
00525         ULOG_ERR_F("connection %p is not open", conn);
00526         return ERIPC_ERROR_INVALID;
00527     }
00528 
00529     make_default_service(destination, service);
00530     make_default_object_path(destination, path);
00531     make_default_interface(destination, interface);
00532 
00533     msg = dbus_message_new_method_call(service, path, interface,
00534                                        message_name);
00535     if (msg == NULL) {
00536         ULOG_ERR_F("dbus_message_new_method_call failed");
00537         return ERIPC_ERROR_OOM;
00538     }
00539 
00540     if (arg_type != ERIPC_TYPE_INVALID) {
00541         eripc_error_t rc;
00542         rc = _append_args(msg, arg_type, va_args);
00543         if (rc != ERIPC_ERROR_SUCCESS) {
00544                 ULOG_ERR_F("invalid type");
00545                 dbus_message_unref(msg);
00546                 return rc;
00547         }
00548     }
00549 
00550     dbus_error_init(&error);
00551     
00552     reply_msg = dbus_connection_send_with_reply_and_block(conn, msg, context->timeout_ms, &error);
00553     dbus_message_unref(msg);
00554 
00555     if (!reply_msg) {
00556         ULOG_ERR_F("dbus_connection_send_with_reply_and_block failed: %s", error.message);
00557         dbus_error_free(&error);
00558         return ERIPC_ERROR_TIMEOUT;
00559     }
00560  
00561     if (reply != NULL) 
00562     {
00563         /* Allocate reply info structure */
00564         eripc_event_info_t *reply_info;
00565         reply_info = calloc(1, sizeof(eripc_event_info_t));
00566         if (reply_info == NULL) {
00567             ULOG_ERR_F("calloc failed");
00568             dbus_message_unref(reply_msg);
00569             return ERIPC_ERROR_OOM;
00570         }
00571 
00572         reply_info->service = dbus_message_get_sender(reply_msg);
00573         reply_info->path = path;
00574         reply_info->interface = interface;
00575         reply_info->name = dbus_message_get_member(reply_msg);
00576         reply_info->bus_type = bus_type;
00577         reply_info->event_type = 0;
00578         
00579         if (dbus_message_get_type(reply_msg) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
00580             _make_id(bus_type, dbus_message_get_sender(reply_msg),
00581                            dbus_message_get_serial(reply_msg), id_buf);
00582             reply_info->message_id = id_buf;
00583         }
00584 
00585         if (dbus_message_get_type(reply_msg) == DBUS_MESSAGE_TYPE_ERROR) {
00586             reply_info->error = dbus_message_get_error_name(reply_msg);
00587         }
00588         
00589         if (dbus_message_iter_init(reply_msg, &iter)) {
00590             reply_info->args = _get_args(&iter);
00591         }
00592         
00593         reply_info->dbus_message = (char*) reply_msg;
00594         
00595         /* Return the pointer to the reply info structure */
00596         *reply = reply_info;
00597     }
00598     else {
00599         /* No reply requested by caller so unref immediately */
00600         dbus_message_unref(reply_msg);
00601     }
00602     
00603     return ERIPC_ERROR_SUCCESS;
00604 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void eripc_reply_handler ( osso_context_t osso,
DBusMessage *  msg,
_osso_callback_data_t cb_data,
eripc_bus_t  dbus_type 
) [static]

Definition at line 178 of file rpc.c.

References _get_args(), _make_id(), eripc_event_info_t::args, eripc_event_info_t::bus_type, _osso_callback_data_t::bus_type, _osso_callback_data_t::data, eripc_convert_msgtype(), ERIPC_TYPE_STRING, eripc_event_info_t::error, osso_af_context_t::error_dummy, eripc_event_info_t::event_type, eripc_event_info_t::interface, MAX_MSGID_LEN, eripc_event_info_t::message_id, _osso_callback_data_t::message_id, eripc_event_info_t::name, eripc_event_info_t::path, osso_af_context_t::reply_dummy, eripc_arg_t::s, eripc_event_info_t::service, eripc_arg_t::type, ULOG_WARN_F, _osso_callback_data_t::user_cb, _osso_callback_data_t::user_data, and eripc_arg_t::value.

Referenced by _send_helper().

00182 {
00183     eripc_event_info_t info;
00184     DBusMessageIter iter;
00185     eripc_handler_t *cb;
00186     int msgtype;
00187     char id_buf[MAX_MSGID_LEN + 1];
00188 
00189     assert(cb_data->message_id == dbus_message_get_reply_serial(msg));
00190     assert(cb_data->bus_type == dbus_type);
00191     assert(cb_data->data == osso);
00192 
00193     /* create a dummy reply message for later use (workaround for
00194      * D-Bus library API) */
00195     if (osso->reply_dummy == NULL) {
00196         DBusMessage *reply;
00197         reply = dbus_message_new_method_return(msg);
00198         if (reply == NULL) {
00199             ULOG_WARN_F("could not create reply_dummy");
00200         } else {
00201             osso->reply_dummy = reply;
00202         }
00203     }
00204     if (osso->error_dummy == NULL) {
00205         DBusMessage *reply;
00206         reply = dbus_message_new_error(msg, "org.foo.dummy", NULL);
00207         if (reply == NULL) {
00208             ULOG_WARN_F("could not create error_dummy");
00209         } else {
00210             osso->error_dummy = reply;
00211         }
00212     }
00213 
00214     memset(&info, 0, sizeof(info));
00215 
00216     msgtype = dbus_message_get_type(msg);
00217     info.service = dbus_message_get_sender(msg);
00218     info.path = dbus_message_get_path(msg);
00219     info.interface = dbus_message_get_interface(msg);
00220     if (msgtype == DBUS_MESSAGE_TYPE_ERROR) {
00221         info.name = dbus_message_get_error_name(msg);
00222     } else {
00223         info.name = dbus_message_get_member(msg);
00224     }
00225     info.bus_type = dbus_type;
00226     _make_id(dbus_type, dbus_message_get_sender(msg),
00227                    dbus_message_get_serial(msg), id_buf);
00228     info.message_id = id_buf;
00229 
00230     info.event_type = eripc_convert_msgtype(msgtype);
00231 
00232     if (dbus_message_iter_init(msg, &iter)) {
00233         info.args = _get_args(&iter);
00234         if (info.args != NULL && msgtype == DBUS_MESSAGE_TYPE_ERROR
00235             && info.args[0].type == ERIPC_TYPE_STRING) {
00236                 info.error = info.args[0].value.s;
00237         }
00238     }
00239 
00240     cb = cb_data->user_cb;
00241     assert(cb != NULL);
00242 
00243     (*cb)((eripc_context_t*)osso, &info, cb_data->user_data);
00244 
00245     if (info.args != NULL) {
00246         free((char*)info.args);
00247         info.args = NULL;
00248     }
00249 }

Here is the call graph for this function:

Here is the caller graph for this function:

Generated by  doxygen 1.6.2-20100208