acquire.c

Go to the documentation of this file.
00001 /*
00002  EasyDbus: DBUS Binding Library.
00003  Copyright (C) 2007  Daniele Rondina aka Ge@@eu, geaaru@gmail.com 
00004 
00005  This program is free software; you can redistribute it and/or
00006  modify it under the terms of the GNU General Public License
00007  as published by the Free Software Foundation; either version 2
00008  of the License, or (at your option) any later version.
00009 
00010  This program is distributed in the hope that it will be useful,
00011  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  GNU General Public License for more details.
00014 
00015  You should have received a copy of the GNU General Public License
00016  along with this program; if not, write to the Free Software
00017  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 
00019   Filename:  acquire.c
00020  
00021   Description:  
00022  
00023   Version:  1.0
00024   Created:  06/07/07 23:49:35 CEST
00025   Revision:  
00026     0 - created (Ge@@ru)
00027     1 - Added doxygen comments
00028  
00029   Author:   Daniele Rondina aka Ge@@ru , geaaru@gmail.com 
00030   License:  GPL 2.0
00031 */
00032 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <unistd.h>
00042 // easydbus includes
00043 #include "easydbus-core.h"
00044 #include "debug.h"
00045 #include "utils.h"
00046 #include "acquire_internal.h"
00047 #include "monitor_internal.h"
00048 #include "message_internal.h"
00049 
00050 
00065 int
00066 easydbus_conn_get_address (EasyDbus_conn * conn,
00067                            char *serviceName,
00068                            enum easydbus_bus bus, int flags)
00069 {
00070    if (serviceName == NULL || conn == NULL)
00071       return -1;
00072 
00073    conn->flags = flags;
00074    conn->bus = bus;
00075    switch (bus) {
00076       case EASYDBUS_SESSION:
00077          return 
00078             easydbus_get_address_onsession (conn, serviceName);
00079          break;
00080       case EASYDBUS_SYSTEM:
00081          return 
00082             easydbus_get_address_onsystem (conn, serviceName);
00083          break;
00084       case EASYDBUS_SESSION_SERVER:
00085          return 
00086             easydbus_get_address_serverSession (conn, serviceName);
00087          break;
00088       default:
00089          break;
00090    }
00091 
00092    return -1;
00093 }
00094 
00111 int
00112 easydbus_conn_reconnect (EasyDbus_conn *conn, int sleep_time) 
00113 {
00114    DBusError err;
00115    int result = -1;
00116    struct EasyDbus_object_box *object;
00117    struct EasyDbus_core *core = 
00118       (struct EasyDbus_core *)conn;
00119    char *new_service_name = NULL;
00120 
00121    if (!conn || !core->service_name)
00122       return -1;
00123 
00124    if (core->conn)
00125       dbus_connection_unref(core->conn);
00126    core->conn = NULL;
00127    conn->registered_ondbus = 0;
00128 
00129    dbus_error_init (&err);
00130 
00131    sleep (sleep_time);
00132 
00133    // Acquire bus address
00134    switch (conn->bus) {
00135       case EASYDBUS_SESSION:
00136       case EASYDBUS_SESSION_SERVER:
00137          if (easydbus_connect_to_bus (core, &err, DBUS_BUS_SESSION))
00138             goto error;
00139          break;
00140       case EASYDBUS_SYSTEM:
00141       case EASYDBUS_SYSTEM_SERVER:
00142          if (easydbus_connect_to_bus (core, &err, DBUS_BUS_SYSTEM))
00143             goto error;
00144          break;
00145       default:
00146          goto error;
00147          break;
00148    }
00149 
00150    result = easydbus_acquire_name (core, core->service_name, 
00151                                    conn->flags, &err);
00152 
00153    if (result == EASYDBUS_CONN_NAME_SERVICE_EXISTS &&
00154        // probably this isn't needed because without this flags
00155        // return value is EASYDBUS_CONN_NAME_SERVICE_IN_QUEUE
00156        (conn->flags & EASYDBUS_CONN_DO_NOT_QUEUE)) {
00157       if (conn->flags & EASYDBUS_CONN_NAME_SERVICE_RENAMED) {
00158          new_service_name = easydbus_found_new_name
00159             (core, core->service_name, conn->flags, &err);
00160          if (new_service_name == NULL)
00161             goto error;
00162          result = EASYDBUS_CONN_NAME_SERVICE_RENAMED;
00163       }
00164       else
00165          goto error;
00166    }
00167 
00168    conn->registered_ondbus = 1;
00169    if (new_service_name) {
00170       if (core->service_name)
00171          free (core->service_name);
00172       core->service_name = new_service_name;
00173    }
00174 
00175    if (core->objects) {
00176       for (object = core->objects; object; 
00177            object = object->next) {
00178          if (!dbus_connection_register_object_path (core->conn,
00179                                      (const char *) object->core.path, 
00180                                                     &object->vtable,
00181                                                     core)) {
00182             EasyDbusDebug ("Error on register object %s", object->core.path);
00183             goto error;
00184          }
00185       }
00186       easydbus_conn_enable_filters (conn);
00187    }
00188 
00189    // check if there is watcher
00190    if (conn->watcher_add_cb && conn->watcher_remove_cb) {
00191       if (easydbus_watcher_enable (conn, conn->watcher_add_cb,
00192                                    conn->watcher_remove_cb,
00193                                    conn->watcher_closure))
00194          goto error;
00195    }
00196 
00197    dbus_error_free (&err);
00198 
00199    return result;
00200 error:
00201    if (conn->registered_ondbus)
00202       dbus_bus_release_name (core->conn, core->service_name, &err);
00203 
00204    if (core->conn != NULL)
00205       dbus_connection_unref (core->conn);
00206 
00207    dbus_error_free (&err);
00208    return -1;
00209 }
00210 
00217 int 
00218 easydbus_conn_set_error_cb (EasyDbus_conn *conn,
00219                             easydbus_error_cb_f cb,
00220                             void *user_closure) 
00221 {
00222   if (!conn || !cb) 
00223      return -1; 
00224 
00225   conn->error_cb = cb;
00226   conn->error_closure = user_closure;
00227 
00228   return 0;
00229 }
00230 
00237 inline int
00238 easydbus_conn_get_n_object (EasyDbus_conn *conn)
00239 {
00240    return (conn ? 
00241            ((struct EasyDbus_core *) conn)->n_objs : -1);
00242 }
00243 
00254 EasyDbus_object *
00255 easydbus_conn_get_object (EasyDbus_conn *conn,
00256                           unsigned int n)
00257 {
00258    int i;
00259    struct EasyDbus_core *core = 
00260       (struct EasyDbus_core *) conn;
00261    struct EasyDbus_object_box *ans = NULL;
00262 
00263    if (conn && (((int) n) <= core->n_objs))
00264       for (i = 0, ans = core->objects;
00265            i < core->n_objs;
00266            i++, ans = ans->next);
00267 
00268    return (EasyDbus_object *) ans;
00269 }
00270 
00278 int
00279 easydbus_conn_set_reply_async_cb (EasyDbus_conn *conn,
00280                                   easydbus_reply_async_cb_f r_cb,
00281                                   void *user_closure)
00282 {
00283    if (!conn || !r_cb)
00284       return -1;
00285    conn->reply_async_cb = r_cb;
00286    conn->reply_async_closure = user_closure;
00287 
00288    return 0;
00289 }
00290 
00297 int
00298 easydbus_conn_set_error_message_cb (EasyDbus_conn *conn,
00299                                     easydbus_error_message_cb_f e_cb,
00300                                     void *user_closure)
00301 {
00302    if (!conn || !e_cb)
00303       return -1;
00304    conn->error_message_cb = e_cb;
00305    conn->error_message_closure = user_closure;
00306 
00307    return 0;
00308 }
00309 
00316 int
00317 easydbus_conn_set_reply_message_cb (EasyDbus_conn *conn,
00318                                     easydbus_reply_message_cb_f r_cb)
00319 {
00320    if (!conn || !r_cb)
00321       return -1;
00322    conn->reply_message_cb = r_cb;
00323 
00324    return 0;
00325 }
00326 
00334 EasyDbus_conn *
00335 easydbus_conn_create (void)
00336 {
00337    struct EasyDbus_core *conn =
00338       (struct EasyDbus_core *)
00339       malloc (sizeof (struct EasyDbus_core));
00340 
00341    if (!conn)
00342       return NULL;
00343 
00344    memset (conn, 0, sizeof (struct EasyDbus_core));
00345 
00346    conn->objects = NULL;
00347    conn->conn = NULL;
00348    conn->service_name = NULL;
00349    conn->watcher = NULL;
00350    conn->handled_ext_signals = NULL;
00351    conn->user_data.error_cb = NULL;
00352    conn->user_data.error_closure = NULL;
00353    conn->user_data.flags = 0;
00354    conn->user_data.bus = EASYDBUS_INVALID;
00355    conn->pending_msgs = NULL;
00356    conn->user_data.reply_async_cb = NULL;
00357    conn->user_data.error_message_cb = NULL;
00358    conn->user_data.error_message_closure = NULL;
00359    conn->user_data.reply_message_cb = NULL;
00360 
00361    return (EasyDbus_conn *) conn;
00362 }
00363 
00368 void 
00369 easydbus_conn_set_closure (EasyDbus_conn *c,
00370                            void *closure)
00371 {
00372    c->closure = closure;
00373 }
00374 
00379 void *
00380 easydbus_conn_get_closure (EasyDbus_conn *c)
00381 {
00382    return (c ? c->closure : NULL);
00383 }
00384 
00402 int
00403 easydbus_conn_destroy (EasyDbus_conn * conn)
00404 {
00405    struct EasyDbus_core *core =
00406       (struct EasyDbus_core *) conn;
00407    struct EasyDbus_object_box *object = NULL;
00408    struct EasyDbus_watcher *watch = NULL;
00409    struct EasyDbus_Pending *p = NULL;
00410    struct EasyDbus_ext_signal *signal = NULL;
00411    DBusError err;
00412    int ret_val = 0;
00413    int i;
00414 
00415    EasyDbusDebug ("Destroy service %s...",
00416                   core->service_name ? core->
00417                   service_name : ".");
00418 
00419    dbus_error_init (&err);
00420 
00421 
00422    if (core->n_objs) {
00423       for (i = 0; i < core->n_objs; i++) {
00424          object = core->objects;
00425          core->objects = object->next;
00426          easydbus_object_unregister (conn, &object->core);
00427          easydbus_object_free_skeleton (&object->core);
00428       }
00429    }
00430 
00431    /* remove external signals */
00432    while (core->handled_ext_signals) {
00433       signal = core->handled_ext_signals;
00434       core->handled_ext_signals = signal->next;
00435       easydbus_ext_signal_free_skeleton (signal);
00436    }
00437 
00438    if (core->conn != NULL) {
00439       if (core->service_name != NULL) {
00440          if (conn->registered_ondbus)
00441             // dbus_bus_release_name (core->conn,
00442             //    core->service_name, &err);
00443             free (core->service_name);
00444          conn->registered_ondbus = 0;
00445       }
00446      
00447       for (p = core->pending_msgs; core->pending_msgs; 
00448            p = core->pending_msgs) {
00449          core->pending_msgs = p->next;
00450          easydbus_pending_destroy(p);
00451       }
00452 
00453       while (core->watcher != NULL) {
00454          watch = core->watcher;
00455          if (conn->watcher_remove_cb && 
00456              dbus_watch_get_enabled (core->watcher->watch))
00457            conn->watcher_remove_cb(core->watcher, 
00458                                    conn->watcher_closure);
00459          core->watcher = core->watcher->next;
00460          free (watch);
00461       }
00462       // use watcher_remove_cb field for detect
00463       // if was watcher.
00464       if (conn->watcher_remove_cb) {
00465          conn->watcher_remove_cb = NULL;
00466          conn->watcher_add_cb = NULL;
00467          // remove watch callbacks. Workaround for resolve problem
00468          // on call of callback when data are invalid.
00469          // (An another solution could be check connection data)
00470          dbus_connection_set_watch_functions (core->conn,
00471                                               NULL, NULL, NULL,
00472                                               NULL, NULL);
00473       } 
00474 
00475       // dbus_connection_remove_filter (core->conn,
00476       //    easydbus_core_filter_func, core);
00477       dbus_connection_unref (core->conn);
00478    }
00479 
00480    free (core);
00481    dbus_error_free (&err);
00482 
00483    return ret_val;
00484 }
00485 
00498 inline int 
00499 easydbus_conn_get_system_service_address (EasyDbus_conn * data, 
00500                                           char *serviceName) 
00501 {
00502    struct EasyDbus_core *core = (struct EasyDbus_core *) data;
00503    char *dbus_starter_address = NULL;
00504    DBusError err;
00505 
00506    dbus_error_init (&err);
00507 
00508    /* recover DBUS_STARTER_ADDRESS environment variable */
00509    dbus_starter_address = getenv ("DBUS_STARTER_ADDRESS");
00510 
00511    if (dbus_starter_address == NULL) {
00512       EasyDbusDebug ("Error on recover dbus_starter_address");
00513       return -1;
00514    }
00515 
00516    core->conn = dbus_connection_open (dbus_starter_address, &err);
00517 
00518    if (!core->conn) {
00519       EasyDbusDebug ("Error %s from "
00520                      "dbus_connection_open: %s",
00521                      err.name, err.message);
00522       return -1;
00523    }
00524 
00525    /* do not allw libdbus to exit on connection failure ( This
00526     * may around random exit () on SIGPIPE errors) */
00527    dbus_connection_set_exit_on_disconnect (core->conn, FALSE);
00528 
00529    dbus_bus_register (core->conn, &err);
00530 
00531    if (dbus_error_is_set (&err)) {
00532       EasyDbusDebug ("Error %s from "
00533                      "dbus_bus_register: %s", err.name, err.message);
00534       goto error_acquire;
00535    }
00536 
00537    /* TODO: manage return values correctly */
00538    /* request for set service name */
00539    dbus_bus_request_name (core->conn, serviceName, 0, &err);
00540 
00541 
00542    if (dbus_error_is_set (&err)) {
00543       EasyDbusDebug ("Error %s from "
00544                      "dbus_bus_request_name: %s",
00545                      err.name, err.message);
00546       goto error_acquire;
00547    }
00548 
00549    /* see if this is correct and what it do. */
00550    //if (set_unique_nameID (core, serviceName)) {
00551    // EasyDbusDebug ("Error on set unique nameID");
00552    // goto error_acquire;
00553    //}
00554 
00555    data->registered_ondbus = 1;
00556 
00557    if (easydbus_save_serviceName (core, serviceName)) {
00558       EasyDbusDebug ("Error on set unique nameID");
00559       goto error_acquire;
00560    }
00561 
00562    dbus_error_free (&err);
00563 
00564    return 0;
00565 
00566  error_acquire:
00567    if (data->registered_ondbus)
00568       dbus_bus_release_name (core->conn, serviceName, &err);
00569 
00570    if (core->conn != NULL)
00571       dbus_connection_unref (core->conn);
00572 
00573    dbus_error_free (&err);
00574 
00575    return -1;
00576 }
00577 
00583 const char *
00584 easydbus_conn_get_service_name (const EasyDbus_conn * conn)
00585 {
00586    return conn ? (const char *)
00587       ((struct EasyDbus_core *)conn)->service_name : NULL;
00588 }
00589 
00599 int
00600 easydbus_conn_get_fd (EasyDbus_conn * data)
00601 {
00602    struct EasyDbus_core *core = (struct EasyDbus_core *) data;
00603    int fd;
00604 
00605    if (data)
00606       //if (dbus_connection_get_fd (core->conn, &fd))
00607       if (dbus_connection_get_unix_fd (core->conn, &fd))
00608          return fd;
00609 
00610    return -1;
00611 }
00612 
00613 // vim: ts=3 shiftwidth=3 expandtab

Generated on Thu Apr 10 10:00:17 2008 for EasyDbus-0.2 by  doxygen 1.5.4