rpc.c

Go to the documentation of this file.
00001 /**
00002  * @file rpc.c
00003  * @brief This file implements rpc calls from one application to another.
00004  */
00005  
00006 /*
00007  * This file is part of liberipc.
00008  *
00009  * liberipc is free software: you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation, either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * liberipc is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00021  */
00022 
00023 /**
00024  * Copyright (C) 2008 iRex Technologies B.V. 
00025  * All rights reserved.
00026  *
00027  * Based on code found in libosso library by Kimmo Hämäläinen <kimmo.hamalainen@nokia.com>
00028  */
00029 
00030 #include "internal.h"
00031 #include <assert.h>
00032 #include <stdlib.h>
00033 
00034 #define UNUSED(x) (void)(x)
00035 
00036 void
00037 _parse_id(const char *id, eripc_bus_t *bus, char *sender,
00038                 int *serial)
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 }
00068 
00069 void
00070 _make_id(eripc_bus_t bus, const char *sender, int serial, char *id)
00071 {
00072     snprintf(id, MAX_MSGID_LEN, "%d,%s,%d", bus, sender, serial);
00073 }
00074 
00075 static eripc_error_t _append_args(DBusMessage *msg, int type,
00076                                         va_list var_args)
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 }
00148 
00149 
00150 eripc_error_t eripc_get_timeout (eripc_context_t *context, int *timeout)
00151 {
00152     if(context == NULL) return ERIPC_ERROR_INVALID;
00153     *timeout = context->timeout_ms;
00154     return ERIPC_ERROR_SUCCESS;
00155 }
00156 
00157 
00158 void *eripc_get_system_connection (eripc_context_t *context)
00159 {
00160     return (void *) context->sys_conn;
00161 }
00162 
00163 void *eripc_get_session_connection (eripc_context_t *context)
00164 {
00165     return (void *) context->conn;
00166 }
00167 
00168 
00169 eripc_error_t eripc_set_timeout(eripc_context_t *context, int timeout)
00170 {
00171     if(context == NULL) return ERIPC_ERROR_INVALID;
00172     context->timeout_ms = timeout;
00173     return ERIPC_ERROR_SUCCESS;
00174 }
00175 
00176 
00177 
00178 static void eripc_reply_handler(osso_context_t *osso,
00179                                 DBusMessage *msg,
00180                                 _osso_callback_data_t *cb_data,
00181                                 eripc_bus_t dbus_type)
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 }
00250 
00251 
00252 static eripc_error_t _send_signal_helper(eripc_context_t *context,
00253                                          eripc_bus_t bus_type,
00254                                          const char *signal_path,
00255                                          const char *signal_interface,
00256                                          const char *signal_name,
00257                                          eripc_data_t arg_type, va_list va_args)
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 }
00308 
00309 
00310 eripc_error_t eripc_send_signal_varargs(eripc_context_t *context,
00311                                         eripc_bus_t bus_type,
00312                                         const char *signal_path,
00313                                         const char *signal_interface,
00314                                         const char *signal_name,
00315                                         eripc_data_t arg_type, ...)
00316 {
00317     va_list va_args;
00318     eripc_error_t rc;
00319 
00320     va_start(va_args, arg_type);
00321     rc = _send_signal_helper(context, bus_type,
00322                              signal_path, signal_interface, signal_name,
00323                              arg_type, va_args);
00324     va_end(va_args);
00325     return rc;
00326 }
00327 
00328 
00329 eripc_error_t eripc_send_signal(eripc_context_t *context,
00330                                 eripc_bus_t bus_type,
00331                                 const char *signal_name,
00332                                 const char *argument)
00333 {
00334     eripc_error_t rc;
00335     
00336     if (argument == NULL)
00337     {        
00338         rc = eripc_send_signal_varargs(context, bus_type, 
00339                                       context->object_path, context->interface, signal_name,
00340                                       ERIPC_TYPE_INVALID);
00341     }
00342     else 
00343     {
00344         rc = eripc_send_signal_varargs(context, bus_type, 
00345                                       context->object_path, context->interface, signal_name,
00346                                       ERIPC_TYPE_STRING, argument,
00347                                       ERIPC_TYPE_INVALID);
00348     }
00349     return rc;
00350 }
00351 
00352 static eripc_error_t _send_helper(eripc_context_t *context,
00353                                   eripc_handler_t *reply_handler,
00354                                   const void *user_data,
00355                                   eripc_bus_t bus_type,
00356                                   const char *destination,
00357                                   const char *message_name,
00358                                   eripc_data_t arg_type, va_list va_args)
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 }
00478 
00479 
00480 static
00481 eripc_error_t _send_sync_helper(eripc_context_t *context,
00482                                 eripc_event_info_t **reply,
00483                                 eripc_bus_t bus_type,
00484                                 const char *destination,
00485                                 const char *message_name,
00486                                 eripc_data_t arg_type, va_list va_args)
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 }
00605 
00606 
00607 eripc_error_t eripc_send_varargs(eripc_context_t *context,
00608                                  eripc_handler_t *reply_handler,
00609                                  const void *user_data,
00610                                  eripc_bus_t bus_type,
00611                                  const char *destination,
00612                                  const char *message_name,
00613                                  eripc_data_t arg_type, ...)
00614 {
00615     va_list va_args;
00616     eripc_error_t rc;
00617 
00618     va_start(va_args, arg_type);
00619     rc = _send_helper(context, reply_handler, user_data,
00620                       bus_type, destination, message_name,
00621                       arg_type, va_args);
00622     va_end(va_args);
00623     return rc;
00624 }
00625 
00626 
00627 eripc_error_t eripc_send_varargs_and_wait(eripc_context_t *context,
00628                                           eripc_event_info_t **reply,
00629                                           eripc_bus_t bus_type,
00630                                           const char *destination,
00631                                           const char *message_name,
00632                                           eripc_data_t arg_type, ...)
00633 {
00634     va_list va_args;
00635     eripc_error_t rc;
00636     
00637     va_start(va_args, arg_type);
00638     rc = _send_sync_helper(context, reply, bus_type, destination,
00639                            message_name, arg_type, va_args);
00640     va_end(va_args);
00641     return rc;   
00642 }
00643 
00644 eripc_error_t eripc_send_string_and_wait(eripc_context_t *context,
00645                                          eripc_event_info_t **reply,
00646                                          eripc_bus_t bus_type,
00647                                          const char *destination,
00648                                          const char *message_name,
00649                                          const char *string_to_send)
00650 
00651 
00652 {
00653     eripc_error_t rc;
00654     rc = eripc_send_varargs_and_wait(context, reply,
00655                                      bus_type, destination, message_name,
00656                                      ERIPC_TYPE_STRING, string_to_send,
00657                                      ERIPC_TYPE_INVALID);
00658     return rc;
00659 }
00660 
00661 eripc_error_t eripc_send_int_and_wait(eripc_context_t *context,
00662                                       eripc_event_info_t **reply,
00663                                       eripc_bus_t bus_type,
00664                                       const char *destination,
00665                                       const char *message_name,
00666                                       int value_to_send)
00667 
00668 
00669 {
00670     eripc_error_t rc;
00671     rc = eripc_send_varargs_and_wait(context, reply,
00672                                      bus_type, destination, message_name,
00673                                      ERIPC_TYPE_INT, value_to_send,
00674                                      ERIPC_TYPE_INVALID);
00675     return rc;
00676 }
00677 
00678 eripc_error_t eripc_send_bool_and_wait(eripc_context_t *context,
00679                                        eripc_event_info_t **reply,
00680                                        eripc_bus_t bus_type,
00681                                        const char *destination,
00682                                        const char *message_name,
00683                                        gboolean value_to_send)
00684 
00685 
00686 {
00687     eripc_error_t rc;
00688     rc = eripc_send_varargs_and_wait(context, reply,
00689                                      bus_type, destination, message_name,
00690                                      ERIPC_TYPE_BOOL, value_to_send,
00691                                      ERIPC_TYPE_INVALID);
00692     return rc;
00693 }
00694 
00695 eripc_error_t eripc_send_string(eripc_context_t *context,
00696                                 eripc_handler_t *reply_handler,
00697                                 const void *user_data,
00698                                 eripc_bus_t bus_type,
00699                                 const char *destination,
00700                                 const char *message_name,
00701                                 const char *string_to_send)
00702 {
00703     eripc_error_t rc;
00704     rc = eripc_send_varargs(context, reply_handler, user_data,
00705                             bus_type, destination, message_name,
00706                             ERIPC_TYPE_STRING, string_to_send,
00707                             ERIPC_TYPE_INVALID);
00708     return rc;
00709 }
00710 
00711 eripc_error_t eripc_send_int(eripc_context_t *context,
00712                              eripc_handler_t *reply_handler,
00713                              const void *user_data,
00714                              eripc_bus_t bus_type,
00715                              const char *destination,
00716                              const char *message_name,
00717                              int value_to_send)
00718 {
00719     eripc_error_t rc;
00720     rc = eripc_send_varargs(context, reply_handler, user_data,
00721                             bus_type, destination, message_name,
00722                             ERIPC_TYPE_INT, value_to_send,
00723                             ERIPC_TYPE_INVALID);
00724     return rc;
00725 }
00726 
00727 eripc_error_t eripc_send_bool(eripc_context_t *context,
00728                               eripc_handler_t *reply_handler,
00729                               const void *user_data,
00730                               eripc_bus_t bus_type,
00731                               const char *destination,
00732                               const char *message_name,
00733                               gboolean value_to_send)
00734 {
00735     eripc_error_t rc;
00736     rc = eripc_send_varargs(context, reply_handler, user_data,
00737                             bus_type, destination, message_name,
00738                             ERIPC_TYPE_BOOL, value_to_send,
00739                             ERIPC_TYPE_INVALID);
00740     return rc;
00741 }
00742 
00743 eripc_error_t eripc_event_info_free(eripc_context_t *context,
00744                                     eripc_event_info_t *info)
00745 {
00746     UNUSED(context);
00747     if (info != NULL) {
00748         if (info->args != NULL) {
00749             free((char*)info->args);
00750         }
00751     
00752         if (info->dbus_message != NULL) {
00753             dbus_message_unref((DBusMessage *)info->dbus_message);
00754         }
00755         
00756         free(info);        
00757     }
00758     
00759     return ERIPC_ERROR_SUCCESS;
00760 }
00761 
00762 static
00763 eripc_error_t _reply_helper(eripc_context_t *context,
00764                             const char *message_id,
00765                             eripc_data_t arg_type, va_list va_args)
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 }
00831 
00832 eripc_error_t eripc_reply_varargs(eripc_context_t *context,
00833                                   const char *message_id,
00834                                   eripc_data_t arg_type, ...)
00835 {
00836     va_list va_args;
00837     eripc_error_t rc;
00838 
00839     va_start(va_args, arg_type);
00840     rc = _reply_helper(context, message_id,
00841                             arg_type, va_args);
00842     va_end(va_args);
00843     return rc;
00844 }
00845 
00846 eripc_error_t eripc_reply_string(eripc_context_t *context,
00847                                  const char *message_id,
00848                                  const char *string)
00849 {
00850     eripc_error_t rc;
00851     rc = eripc_reply_varargs(context, message_id,
00852                              ERIPC_TYPE_STRING, string,
00853                              ERIPC_TYPE_INVALID);
00854     return rc;
00855 }
00856 
00857 eripc_error_t eripc_reply_int(eripc_context_t *context,
00858                               const char *message_id,
00859                               int value)
00860 {
00861     eripc_error_t rc;
00862     rc = eripc_reply_varargs(context, message_id,
00863                              ERIPC_TYPE_INT, value,
00864                              ERIPC_TYPE_INVALID);
00865     return rc;
00866 }
00867 
00868 eripc_error_t eripc_reply_bool(eripc_context_t *context,
00869                                const char *message_id,
00870                                gboolean value)
00871 {
00872     eripc_error_t rc;
00873     rc = eripc_reply_varargs(context, message_id,
00874                              ERIPC_TYPE_BOOL, value,
00875                              ERIPC_TYPE_INVALID);
00876     return rc;
00877 }
00878 
00879 eripc_error_t eripc_reply_error(eripc_context_t *context,
00880                                 const char *message_id,
00881                                 const char *name,
00882                                 const char *message)
00883 {
00884     DBusConnection *conn;
00885     DBusMessage *reply;
00886     dbus_bool_t ret;
00887     char sender[MAX_SVC_LEN + 1], error_name[MAX_ERROR_LEN + 1];
00888     int serial;
00889     eripc_bus_t bus_type;
00890 
00891     if (context == NULL || name == NULL || message_id == NULL) {
00892         return ERIPC_ERROR_INVALID;
00893     }
00894     if (context->error_dummy == NULL) {
00895         /* OOM has happened earlier in the handler, or
00896          * the context is invalid */
00897         ULOG_ERR_F("error_dummy has not been created");
00898         return ERIPC_ERROR;
00899     }
00900 
00901     _parse_id(message_id, &bus_type, sender, &serial);
00902     assert(bus_type == ERIPC_BUS_SYSTEM || bus_type == ERIPC_BUS_SESSION);
00903 
00904     if (bus_type == ERIPC_BUS_SYSTEM) {
00905         conn = context->sys_conn;
00906     } else {
00907         conn = context->conn;
00908     }
00909     if (!dbus_connection_get_is_connected(conn)) {
00910         ULOG_ERR_F("connection %p is not open", conn);
00911         return ERIPC_ERROR_INVALID;
00912     }
00913 
00914     make_default_error_name(context->service, name, error_name);
00915 
00916     /* make a copy of the error_dummy and modify the copy */
00917     reply = dbus_message_copy(context->error_dummy);
00918     if (reply == NULL) {
00919         ULOG_ERR_F("dbus_message_copy failed");
00920         return ERIPC_ERROR_OOM;
00921     }
00922     if (!dbus_message_set_destination(reply, sender)) {
00923         ULOG_ERR_F("dbus_message_set_destination failed");
00924         goto unref_and_exit;
00925     }
00926     if (!dbus_message_set_reply_serial(reply, serial)) {
00927         ULOG_ERR_F("dbus_message_set_reply_serial failed");
00928         goto unref_and_exit;
00929     }
00930     if (!dbus_message_set_error_name(reply, error_name)) {
00931         ULOG_ERR_F("dbus_message_set_error_name failed");
00932         goto unref_and_exit;
00933     }
00934 
00935     if (message != NULL) {
00936         ret = dbus_message_append_args(reply, DBUS_TYPE_STRING,
00937                                        &message,
00938                                        DBUS_TYPE_INVALID);
00939         if (!ret) {
00940             ULOG_ERR_F("dbus_message_append_args failed");
00941             goto unref_and_exit;
00942         }
00943     }
00944 
00945     if (!dbus_connection_send(conn, reply, NULL)) {
00946         ULOG_ERR_F("dbus_connection_send failed");
00947         goto unref_and_exit;
00948     }
00949     dbus_message_unref(reply);
00950     return ERIPC_ERROR_SUCCESS;
00951 
00952 unref_and_exit:
00953     dbus_message_unref(reply);
00954     return ERIPC_ERROR_OOM;
00955 }
Generated by  doxygen 1.6.2-20100208