00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "stdio.h"
00031 #include "internal.h"
00032 #include "init.h"
00033 #include <assert.h>
00034 #include "eripc.h"
00035
00036 #define UNUSED(x) (void)(x)
00037
00038 static DBusHandlerResult
00039 _filter_session(DBusConnection *conn, DBusMessage *msg, void *data);
00040
00041 static DBusHandlerResult
00042 _filter_system(DBusConnection *conn, DBusMessage *msg, void *data);
00043
00044 inline static DBusHandlerResult
00045 _filter(DBusConnection *conn, DBusMessage *msg, void *data,
00046 eripc_bus_t dbus_type);
00047
00048 static const char *opm_match_all_key = ERIPC_PATH_MATCH_ALL
00049 ERIPC_MEMBER_MATCH_ALL;
00050
00051 inline static void
00052 compose_opm_hash_key(const char *object_path, const char *member,
00053 char *key)
00054 {
00055 key[0] = '\0';
00056 if (object_path == NULL && member == NULL) {
00057 strncat(key, opm_match_all_key, MAX_OP_LEN + MAX_MEMBER_LEN);
00058 } else if (object_path == NULL) {
00059 strncat(key, ERIPC_PATH_MATCH_ALL, MAX_OP_LEN);
00060 strncat(key, member, MAX_MEMBER_LEN);
00061 } else if (member == NULL) {
00062 strncat(key, object_path, MAX_OP_LEN);
00063 strncat(key, ERIPC_MEMBER_MATCH_ALL, MAX_MEMBER_LEN);
00064 } else {
00065 strncat(key, object_path, MAX_OP_LEN);
00066 strncat(key, member, MAX_MEMBER_LEN);
00067 }
00068 }
00069
00070 gboolean __attribute__ ((visibility("hidden")))
00071 validate_appname(const gchar *application)
00072 {
00073 if (application == NULL || strstr(application, "/") != NULL) {
00074 return FALSE;
00075 }
00076 return TRUE;
00077 }
00078
00079
00080
00081 eripc_context_t *eripc_init(const char *program_name,
00082 const char *program_version,
00083 GMainContext *context)
00084 {
00085 osso_context_t *osso;
00086
00087 char *name = strdup(program_name);
00088 if (name == NULL) {
00089 ULOG_CRIT_F("initialisation failed: out of memory");
00090 return NULL;
00091 }
00092
00093
00094 unsigned int i;
00095 for (i=0; i<strlen(name); i++)
00096 {
00097 if (name[i] == '-')
00098 name[i] = '_';
00099 }
00100
00101 ULOG_DEBUG_F("program '%s', version '%s'", name,
00102 program_version);
00103
00104 osso = _init(name, program_version);
00105 free(name);
00106 if (osso == NULL) {
00107 ULOG_CRIT_F("initialisation failed: out of memory");
00108 return NULL;
00109 }
00110
00111 osso->conn = _dbus_setup(osso, DBUS_BUS_SESSION, context);
00112 if (osso->conn == NULL) {
00113 ULOG_CRIT_F("connecting to the session bus failed");
00114 _deinit(osso);
00115 return NULL;
00116 }
00117 osso->sys_conn = _dbus_setup(osso, DBUS_BUS_SYSTEM, context);
00118 if (osso->sys_conn == NULL) {
00119 ULOG_CRIT_F("connecting to the system bus failed");
00120 _deinit(osso);
00121 return NULL;
00122 }
00123 osso->eripc_filters_setup = TRUE;
00124 osso->cur_conn = NULL;
00125 return (eripc_context_t*)osso;
00126 }
00127
00128
00129
00130 static gboolean _validate(const gchar *application, const gchar* version)
00131 {
00132 if (application == NULL || version == NULL) {
00133 return FALSE;
00134 }
00135 if (!validate_appname(application)) {
00136 return FALSE;
00137 }
00138 if (strchr(version, '/') != NULL) {
00139 ULOG_ERR_F("invalid version string '%s'", version);
00140 return FALSE;
00141 }
00142 return TRUE;
00143 }
00144
00145 void __attribute__ ((visibility("hidden")))
00146 make_default_interface(const char *application, char *interface)
00147 {
00148 assert(application != NULL);
00149 assert(interface != NULL);
00150
00151 if (g_strrstr(application, ".") != NULL) {
00152 g_snprintf(interface, MAX_IF_LEN, "%s", application);
00153 } else {
00154 g_snprintf(interface, MAX_IF_LEN, OSSO_BUS_ROOT ".%s",
00155 application);
00156 }
00157 }
00158
00159 void __attribute__ ((visibility("hidden")))
00160 make_default_error_name(const char *service, const char *name,
00161 char *ready_name)
00162 {
00163 assert(service != NULL);
00164 assert(name != NULL);
00165 assert(ready_name != NULL);
00166
00167 if (g_strrstr(name, ".") != NULL) {
00168 g_snprintf(ready_name, MAX_ERROR_LEN, "%s", name);
00169 } else {
00170 g_snprintf(ready_name, MAX_ERROR_LEN, "%s.%s", service, name);
00171 }
00172 }
00173
00174 void __attribute__ ((visibility("hidden")))
00175 make_default_service(const char *application, char *service)
00176 {
00177 assert(application != NULL);
00178 assert(service != NULL);
00179
00180 if (g_strrstr(application, ".") != NULL) {
00181 g_snprintf(service, MAX_SVC_LEN, "%s", application);
00182 } else {
00183 g_snprintf(service, MAX_SVC_LEN, OSSO_BUS_ROOT ".%s",
00184 application);
00185 }
00186 }
00187
00188 void __attribute__ ((visibility("hidden")))
00189 make_default_object_path(const char *application, char *path)
00190 {
00191 char component[MAX_OP_LEN + 1], *p;
00192
00193 assert(application != NULL);
00194 assert(path != NULL);
00195
00196 strncpy(component, application, MAX_OP_LEN);
00197 component[MAX_OP_LEN] = '\0';
00198
00199 for (p = component; *p != '\0'; ++p) {
00200 if (*p == '.') {
00201 *p = '/';
00202 }
00203 }
00204
00205 if (strchr(application, '.') != NULL) {
00206 g_snprintf(path, MAX_OP_LEN, "/%s", component);
00207 } else {
00208 g_snprintf(path, MAX_OP_LEN, OSSO_BUS_ROOT_PATH "/%s", component);
00209 }
00210 }
00211
00212
00213
00214 static void free_handler(gpointer data, gpointer user_data)
00215 {
00216 UNUSED(user_data);
00217 _osso_handler_t *h = data;
00218
00219 if (h != NULL) {
00220 if (h->can_free_data) {
00221 free(h->data);
00222 h->data = NULL;
00223 }
00224 free(h);
00225 }
00226 }
00227
00228 static void free_uniq_hash_value(gpointer data)
00229 {
00230 _osso_hash_value_t *elem = data;
00231
00232 if (elem != NULL) {
00233 if (elem->handlers != NULL) {
00234 g_slist_foreach(elem->handlers, free_handler, NULL);
00235 g_slist_free(elem->handlers);
00236 elem->handlers = NULL;
00237 }
00238 free(elem);
00239 }
00240 }
00241
00242 static void free_if_hash_value(gpointer data)
00243 {
00244 _osso_hash_value_t *elem = data;
00245
00246 if (elem != NULL) {
00247 if (elem->handlers != NULL) {
00248 g_slist_free(elem->handlers);
00249 elem->handlers = NULL;
00250 }
00251 free(elem);
00252 }
00253 }
00254
00255 static osso_context_t *_init(const char *application,
00256 const char *version)
00257 {
00258 osso_context_t *osso;
00259
00260 if (!_validate(application, version)) {
00261 ULOG_ERR_F("invalid arguments");
00262 return NULL;
00263 }
00264
00265 osso = calloc(1, sizeof(osso_context_t));
00266 if (osso == NULL) {
00267 ULOG_ERR_F("calloc failed");
00268 return NULL;
00269 }
00270
00271 g_snprintf(osso->application, MAX_APP_NAME_LEN, "%s", application);
00272 g_snprintf(osso->version, MAX_VERSION_LEN, "%s", version);
00273 make_default_interface((const char*)application, osso->interface);
00274 make_default_service((const char*)application, osso->service);
00275 make_default_object_path((const char*)application, osso->object_path);
00276
00277 osso->opm_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
00278 free, free_if_hash_value);
00279 osso->id_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
00280 NULL, free_uniq_hash_value);
00281 if (osso->id_hash == NULL || osso->opm_hash == NULL) {
00282 ULOG_ERR_F("g_hash_table_new_full failed");
00283 free(osso);
00284 return NULL;
00285 }
00286 osso->cp_plugins = g_hash_table_new(g_str_hash, g_str_equal);
00287 osso->timeout_ms = 500;
00288 osso->next_handler_id = 1;
00289 return osso;
00290 }
00291
00292
00293
00294 static void _deinit(osso_context_t *osso)
00295 {
00296 if (osso == NULL) {
00297 return;
00298 }
00299 if (osso->uniq_hash != NULL) {
00300 g_hash_table_destroy(osso->uniq_hash);
00301 }
00302 if (osso->if_hash != NULL) {
00303 g_hash_table_destroy(osso->if_hash);
00304 }
00305 if (osso->opm_hash != NULL) {
00306 g_hash_table_destroy(osso->opm_hash);
00307 }
00308 if (osso->id_hash != NULL) {
00309 g_hash_table_destroy(osso->id_hash);
00310 }
00311 if (osso->cp_plugins != NULL) {
00312 g_hash_table_destroy(osso->cp_plugins);
00313 }
00314
00315 memset(osso, 0, sizeof(osso_context_t));
00316 free(osso);
00317 osso = NULL;
00318 }
00319
00320
00321
00322 static DBusConnection *_dbus_setup(osso_context_t*osso,
00323 DBusBusType bus_type,
00324 GMainContext *context)
00325 {
00326 DBusConnection *conn;
00327 DBusError err;
00328 int ret;
00329
00330 dbus_error_init(&err);
00331
00332
00333
00334 conn = dbus_bus_get(bus_type, &err);
00335 if (conn == NULL) {
00336 ULOG_ERR_F("Unable to connect to the D-Bus %s bus: %s",
00337 bus_type == DBUS_BUS_SESSION ? "session" : "system",
00338 err.message);
00339 dbus_error_free(&err);
00340 return NULL;
00341 }
00342 dbus_connection_setup_with_g_main(conn, context);
00343
00344 ret = dbus_bus_request_name(conn, osso->service,
00345 DBUS_NAME_FLAG_ALLOW_REPLACEMENT, &err);
00346 if (ret == -1) {
00347 ULOG_ERR_F("dbus_bus_request_name failed: %s", err.message);
00348 dbus_error_free(&err);
00349 return NULL;
00350 }
00351
00352 dbus_connection_set_exit_on_disconnect(conn, FALSE);
00353
00354 if (bus_type == DBUS_BUS_SESSION) {
00355 if (!dbus_connection_add_filter(conn, _filter_session,
00356 osso, NULL)) {
00357 ULOG_ERR_F("dbus_connection_add_filter failed");
00358 return NULL;
00359 }
00360 } else {
00361 if (!dbus_connection_add_filter(conn, _filter_system,
00362 osso, NULL)) {
00363 ULOG_ERR_F("dbus_connection_add_filter failed");
00364 return NULL;
00365 }
00366 }
00367
00368 dprint("My base service is '%s'", dbus_bus_get_unique_name(conn));
00369
00370 return conn;
00371 }
00372
00373
00374
00375 DBusHandlerResult __attribute__ ((visibility("hidden")))
00376 _msg_handler(DBusConnection *conn, DBusMessage *msg, void *data)
00377 {
00378 osso_context_t *osso;
00379 _osso_hash_value_t *elem;
00380 gboolean is_method;
00381 const char *interface;
00382 gboolean found = FALSE;
00383
00384 osso = data;
00385
00386 assert(osso != NULL);
00387
00388 if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
00389 is_method = TRUE;
00390 else if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_SIGNAL)
00391 is_method = FALSE;
00392 else
00393 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00394
00395
00396
00397 interface = dbus_message_get_interface(msg);
00398
00399 if (interface == NULL) {
00400 ULOG_DEBUG_F("interface of the message was NULL");
00401 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00402 }
00403
00404 ULOG_DEBUG_F("key = '%s'", interface);
00405 elem = g_hash_table_lookup(osso->if_hash, interface);
00406
00407 if (elem != NULL) {
00408 GSList *list;
00409
00410 osso->cur_conn = conn;
00411 ULOG_DEBUG_F(" elem");
00412
00413 list = elem->handlers;
00414 while (list != NULL) {
00415 _osso_handler_t *handler;
00416
00417 handler = list->data;
00418
00419 ULOG_DEBUG_F(" list");
00420
00421 if (handler->method == is_method) {
00422 ULOG_DEBUG_F("before calling the handler");
00423 ULOG_DEBUG_F(" handler = %p", handler->handler);
00424 ULOG_DEBUG_F(" data = %p", handler->data);
00425 (*handler->handler)(osso, msg, handler->data, 0);
00426 ULOG_DEBUG_F("after calling the handler");
00427 found = TRUE;
00428 }
00429
00430 list = g_slist_next(list);
00431 }
00432 }
00433
00434 if (!found) {
00435 ULOG_DEBUG_F("suitable handler not found from the hash table");
00436 }
00437
00438 #if 0
00439 for(i=0; i<osso->ifs->len; i++) {
00440 _osso_interface_t *intf;
00441 DBusHandlerResult r;
00442 intf = &g_array_index(osso->ifs, _osso_interface_t, i);
00443 if(intf->method == is_method) {
00444
00445 if(strcmp(interface, intf->interface) == 0) {
00446
00447 r = (intf->handler)(osso, msg, intf->data);
00448 if(r == DBUS_HANDLER_RESULT_HANDLED) {
00449 return r;
00450 }
00451 }
00452 }
00453 }
00454 #endif
00455
00456 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00457 }
00458
00459 int
00460 eripc_convert_msgtype(int t)
00461 {
00462 switch (t) {
00463 case DBUS_MESSAGE_TYPE_METHOD_CALL:
00464 return ERIPC_EVENT_MESSAGE;
00465 case DBUS_MESSAGE_TYPE_SIGNAL:
00466 return ERIPC_EVENT_SIGNAL;
00467 case DBUS_MESSAGE_TYPE_ERROR:
00468 return ERIPC_EVENT_ERROR;
00469 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
00470 return ERIPC_EVENT_REPLY;
00471 default:
00472 ULOG_ERR_F("unknown message type %d", t);
00473 return ERIPC_EVENT_NONE;
00474 }
00475 }
00476
00477 inline static int types_match(int a, int b)
00478 {
00479 if (a == b) return 1;
00480
00481 if (a == ERIPC_EVENT_MESSAGE_OR_SIGNAL &&
00482 (b == ERIPC_EVENT_MESSAGE || b == ERIPC_EVENT_SIGNAL))
00483 return 1;
00484
00485 if (a == ERIPC_EVENT_REPLY_OR_ERROR &&
00486 (b == ERIPC_EVENT_REPLY || b == ERIPC_EVENT_ERROR))
00487 return 1;
00488
00489 if (b == ERIPC_EVENT_MESSAGE_OR_SIGNAL &&
00490 (a == ERIPC_EVENT_MESSAGE || a == ERIPC_EVENT_SIGNAL))
00491 return 1;
00492
00493 if (b == ERIPC_EVENT_REPLY_OR_ERROR &&
00494 (a == ERIPC_EVENT_REPLY || a == ERIPC_EVENT_ERROR))
00495 return 1;
00496
00497 return 0;
00498 }
00499
00500 inline static int str_match(const char *a, const char *b)
00501 {
00502 if (a == NULL || b == NULL) return 1;
00503
00504 if (strcmp(a, b) == 0) return 1;
00505
00506 return 0;
00507 }
00508
00509 static DBusHandlerResult
00510 _filter_session(DBusConnection *conn, DBusMessage *msg, void *data)
00511 {
00512 return _filter(conn, msg, data, ERIPC_BUS_SESSION);
00513 }
00514
00515 static DBusHandlerResult
00516 _filter_system(DBusConnection *conn, DBusMessage *msg, void *data)
00517 {
00518 return _filter(conn, msg, data, ERIPC_BUS_SYSTEM);
00519 }
00520
00521 inline static void opm_match_helper(const char *object_path,
00522 const char *member,
00523 char *key)
00524 {
00525 key[0] = '\0';
00526 strncat(key, object_path, MAX_OP_LEN);
00527 strncat(key, member, MAX_MEMBER_LEN);
00528 }
00529
00530
00531 inline static GSList *opm_match(osso_context_t *ipc,
00532 const char *path,
00533 const char *member)
00534 {
00535 GSList *list = NULL;
00536 _osso_hash_value_t *elem;
00537 char opm_key[MAX_OPM_HASH_KEY_LEN + 1];
00538
00539 if (path != NULL && member != NULL) {
00540
00541 opm_match_helper(path, member, opm_key);
00542 elem = g_hash_table_lookup(ipc->opm_hash, opm_key);
00543 if (elem != NULL) list = g_slist_prepend(list, elem);
00544 }
00545
00546
00547 elem = g_hash_table_lookup(ipc->opm_hash, opm_match_all_key);
00548 if (elem != NULL) list = g_slist_prepend(list, elem);
00549
00550 if (member != NULL) {
00551
00552 opm_match_helper(ERIPC_PATH_MATCH_ALL, member, opm_key);
00553 elem = g_hash_table_lookup(ipc->opm_hash, opm_key);
00554 if (elem != NULL) list = g_slist_prepend(list, elem);
00555 }
00556
00557 if (path != NULL) {
00558
00559 opm_match_helper(path, ERIPC_MEMBER_MATCH_ALL, opm_key);
00560 elem = g_hash_table_lookup(ipc->opm_hash, opm_key);
00561 if (elem != NULL) list = g_slist_prepend(list, elem);
00562 }
00563
00564 return list;
00565 }
00566
00567
00568 inline static DBusHandlerResult
00569 _filter(DBusConnection *conn, DBusMessage *msg, void *data,
00570 eripc_bus_t dbus_type)
00571 {
00572 osso_context_t *ipc;
00573 GSList *elem_list, *elem_list_p, *rm_list = NULL, *rm_list_p;
00574 int msgtype;
00575 unsigned int reply_to;
00576 gboolean found = FALSE;
00577
00578 ipc = data;
00579
00580 assert(ipc != NULL);
00581 ipc->cur_conn = conn;
00582
00583 msgtype = eripc_convert_msgtype(dbus_message_get_type(msg));
00584 if (msgtype == ERIPC_EVENT_NONE) {
00585 ULOG_DEBUG_F("_filter: ERIPC_EVENT_NONE");
00586 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00587 }
00588 reply_to = dbus_message_get_reply_serial(msg);
00589
00590 elem_list = opm_match(ipc, dbus_message_get_path(msg),
00591 dbus_message_get_member(msg));
00592
00593 elem_list_p = elem_list;
00594 while (elem_list_p != NULL) {
00595 _osso_hash_value_t *elem;
00596
00597 elem = elem_list_p->data;
00598
00599 if (elem != NULL) {
00600 GSList *list;
00601 int last_id = 0;
00602
00603 list = elem->handlers;
00604 while (list != NULL) {
00605 _osso_handler_t *handler;
00606 _osso_callback_data_t *cb_data;
00607 gboolean match_sender = TRUE;
00608
00609 handler = list->data;
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 if (handler->call_once_per_handler_id
00638 && handler->handler_id == last_id) {
00639
00640
00641 ULOG_DEBUG_F("handler already called, skip");
00642 list = g_slist_next(list);
00643 continue;
00644 }
00645
00646 cb_data = handler->data;
00647
00648 if (cb_data != NULL && cb_data->message_id != 0
00649 && cb_data->message_id == reply_to) {
00650
00651
00652 ULOG_DEBUG_F("calling one-shot handler at %p,"
00653 " data=%p", handler->handler, cb_data);
00654 (*handler->handler)(ipc, msg, cb_data, dbus_type);
00655 ULOG_DEBUG_F("after calling handler at %p",
00656 handler->handler);
00657 found = TRUE;
00658
00659
00660
00661 rm_list = g_slist_prepend(rm_list,
00662 GINT_TO_POINTER(handler->handler_id));
00663
00664 list = g_slist_next(list);
00665 continue;
00666 }
00667
00668 if (cb_data != NULL && cb_data->bus_type != ERIPC_BUS_BOTH
00669 && cb_data->bus_type != dbus_type) {
00670
00671 ULOG_DEBUG_F("handler is not for this bus type, skip");
00672 list = g_slist_next(list);
00673 continue;
00674 }
00675
00676 if (msgtype == ERIPC_EVENT_SIGNAL) {
00677
00678
00679
00680
00681 match_sender = FALSE;
00682 }
00683
00684 if (cb_data != NULL &&
00685 types_match(cb_data->event_type, msgtype) &&
00686 (!match_sender || str_match(cb_data->service,
00687 dbus_message_get_sender(msg))) &&
00688 str_match(cb_data->interface,
00689 dbus_message_get_interface(msg))) {
00690
00691
00692 ULOG_DEBUG_F("before calling the handler at %p, data=%p",
00693 handler->handler, cb_data);
00694 (*handler->handler)(ipc, msg, cb_data, dbus_type);
00695 ULOG_DEBUG_F("after calling handler at %p",
00696 handler->handler);
00697 found = TRUE;
00698 }
00699
00700 last_id = handler->handler_id;
00701 list = g_slist_next(list);
00702 }
00703 }
00704
00705 elem_list_p = g_slist_next(elem_list_p);
00706 }
00707
00708 if (elem_list != NULL) {
00709 g_slist_free(elem_list);
00710 }
00711
00712 if (rm_list != NULL) {
00713 rm_list_p = rm_list;
00714 do {
00715 gboolean ret;
00716 int handler_id = GPOINTER_TO_INT(rm_list_p->data);
00717
00718 assert(handler_id != 0);
00719 ret = _unset_handler(ipc, handler_id);
00720 assert(ret);
00721
00722 rm_list_p = g_slist_next(rm_list_p);
00723 } while (rm_list_p != NULL);
00724 g_slist_free(rm_list);
00725 }
00726
00727 if (!found) {
00728 ULOG_DEBUG_F("suitable handler not found for '%s/%s'",
00729 dbus_message_get_path(msg),
00730 dbus_message_get_member(msg));
00731 }
00732 else {
00733 return DBUS_HANDLER_RESULT_HANDLED;
00734 }
00735 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00736 }
00737
00738
00739
00740 static gboolean add_to_opm_hash(osso_context_t *osso,
00741 const _osso_handler_t *handler,
00742 const char *opm_key)
00743 {
00744 _osso_hash_value_t *old;
00745
00746 old = g_hash_table_lookup(osso->opm_hash, opm_key);
00747 if (old != NULL) {
00748 old->handlers = g_slist_append(old->handlers,
00749 (_osso_handler_t*)handler);
00750 } else {
00751 _osso_hash_value_t *new_elem;
00752 char *new_key;
00753
00754
00755 new_elem = calloc(1, sizeof(_osso_hash_value_t));
00756 if (new_elem == NULL) {
00757 ULOG_ERR_F("calloc() failed");
00758 return FALSE;
00759 }
00760
00761 new_key = strdup(opm_key);
00762 if (new_key == NULL) {
00763 ULOG_ERR_F("calloc() failed");
00764 free(new_elem);
00765 return FALSE;
00766 }
00767
00768 new_elem->handlers = g_slist_append(NULL, (_osso_handler_t*)handler);
00769
00770 g_hash_table_insert(osso->opm_hash, new_key, new_elem);
00771 }
00772 return TRUE;
00773 }
00774
00775 gboolean __attribute__ ((visibility("hidden")))
00776 _eripc_set_handler(_eripc_context_t *context,
00777 _osso_handler_f *handler,
00778 _osso_callback_data_t *data,
00779 int handler_id,
00780 gboolean call_once_per_handler_id)
00781 {
00782 char opm_key[MAX_OPM_HASH_KEY_LEN + 1];
00783 _osso_hash_value_t *old;
00784 _osso_handler_t *elem;
00785
00786 assert(context != NULL && handler != NULL && data != NULL);
00787 assert(handler_id != 0);
00788
00789 compose_opm_hash_key(data->path, data->name, opm_key);
00790
00791 elem = calloc(1, sizeof(_osso_handler_t));
00792 if (elem == NULL) {
00793 ULOG_ERR_F("calloc() failed");
00794 return FALSE;
00795 }
00796
00797 elem->handler = handler;
00798 elem->data = data;
00799 elem->handler_id = handler_id;
00800 elem->call_once_per_handler_id = call_once_per_handler_id;
00801
00802
00803 old = g_hash_table_lookup(context->id_hash, GINT_TO_POINTER(handler_id));
00804 if (old != NULL) {
00805 ULOG_DEBUG_F("registering another handler for id %d", handler_id);
00806
00807
00808 old->handlers = g_slist_append(old->handlers, elem);
00809
00810 } else {
00811 _osso_hash_value_t *new_elem;
00812
00813 ULOG_DEBUG_F("registering first handler for id %d", handler_id);
00814
00815
00816 new_elem = calloc(1, sizeof(_osso_hash_value_t));
00817 if (new_elem == NULL) {
00818 ULOG_ERR_F("calloc() failed");
00819 free(elem);
00820 return FALSE;
00821 }
00822
00823 new_elem->handlers = g_slist_append(NULL, elem);
00824
00825 g_hash_table_insert(context->id_hash, GINT_TO_POINTER(handler_id),
00826 new_elem);
00827 }
00828
00829 return add_to_opm_hash(context, elem, opm_key);
00830 }
00831
00832 static void remove_from_opm_hash(_eripc_context_t *context,
00833 int handler_id,
00834 const char *opm_key)
00835 {
00836 _osso_hash_value_t *elem;
00837
00838 elem = g_hash_table_lookup(context->opm_hash, opm_key);
00839 if (elem != NULL) {
00840 GSList *list;
00841
00842 list = elem->handlers;
00843 while (list != NULL) {
00844 _osso_handler_t *h = list->data;
00845 GSList *next_elem;
00846
00847 next_elem = g_slist_next(list);
00848
00849 if (h->handler_id == handler_id) {
00850 ULOG_DEBUG_F("found handler_id %d from if_hash", handler_id);
00851 elem->handlers = g_slist_remove_link(elem->handlers, list);
00852 g_slist_free_1(list);
00853
00854
00855
00856 if (g_slist_length(elem->handlers) == 0) {
00857 g_hash_table_remove(context->opm_hash, opm_key);
00858 return;
00859 }
00860 }
00861 list = next_elem;
00862 }
00863 }
00864 }
00865
00866 gboolean __attribute__ ((visibility("hidden")))
00867 _unset_handler(_eripc_context_t *context, int handler_id)
00868 {
00869 _osso_hash_value_t *elem;
00870 GSList *list;
00871
00872 ULOG_DEBUG_F("context=%p", context);
00873 elem = g_hash_table_lookup(context->id_hash, GINT_TO_POINTER(handler_id));
00874 if (elem == NULL) {
00875 ULOG_ERR_F("couldn't find handler_id %d from id_hash", handler_id);
00876 return FALSE;
00877 }
00878
00879
00880 list = elem->handlers;
00881 while (list != NULL) {
00882 char opm_key[MAX_OPM_HASH_KEY_LEN + 1];
00883 DBusError err;
00884 _osso_handler_t *h = list->data;
00885
00886 compose_opm_hash_key(h->data->path, h->data->name, opm_key);
00887 remove_from_opm_hash(context, handler_id, opm_key);
00888
00889 dbus_error_init(&err);
00890
00891 if (h->data->match_rule && (h->data->bus_type == ERIPC_BUS_SYSTEM
00892 || h->data->bus_type == ERIPC_BUS_BOTH)) {
00893 dbus_bus_remove_match(context->sys_conn, h->data->match_rule,
00894 &err);
00895 if (dbus_error_is_set(&err)) {
00896 ULOG_WARN_F("dbus_bus_remove_match failed for %s: %s",
00897 h->data->match_rule, err.message);
00898 dbus_error_free(&err);
00899 dbus_error_init(&err);
00900 }
00901 }
00902
00903 if (h->data->match_rule && (h->data->bus_type == ERIPC_BUS_SESSION
00904 || h->data->bus_type == ERIPC_BUS_BOTH)) {
00905 dbus_bus_remove_match(context->conn, h->data->match_rule,
00906 &err);
00907 if (dbus_error_is_set(&err)) {
00908 ULOG_WARN_F("dbus_bus_remove_match failed for %s: %s",
00909 h->data->match_rule, err.message);
00910 dbus_error_free(&err);
00911 }
00912 }
00913
00914 free(h->data->service); h->data->service = NULL;
00915 if (h->data->path != NULL
00916 && strcmp(ERIPC_PATH_MATCH_ALL, h->data->path) != 0) {
00917 free(h->data->path); h->data->path = NULL;
00918 }
00919 free(h->data->interface); h->data->interface = NULL;
00920 if (h->data->name != NULL
00921 && strcmp(ERIPC_MEMBER_MATCH_ALL, h->data->name) != 0) {
00922 free(h->data->name); h->data->name = NULL;
00923 }
00924 free(h->data); h->data = NULL;
00925
00926 list = g_slist_next(list);
00927 }
00928
00929 if (!g_hash_table_remove(context->id_hash, GINT_TO_POINTER(handler_id))) {
00930 ULOG_ERR_F("couldn't find handler_id %d from id_hash", handler_id);
00931 assert(0);
00932 }
00933
00934 return TRUE;
00935 }