4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * @file edbus-handler.c
23 * @desc dbus handler using edbus interface
25 * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
30 #include "edbus-handler.h"
32 #include "resourced.h"
34 #define EDBUS_INIT_RETRY_COUNT 5
38 E_DBus_Signal_Handler *handler;
41 static struct edbus_object edbus_objects[] = {
42 { RESOURCED_PATH_SWAP, RESOURCED_INTERFACE_SWAP , NULL, NULL },
43 { RESOURCED_PATH_OOM, RESOURCED_INTERFACE_OOM, NULL, NULL },
44 { RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS, NULL, NULL },
45 { RESOURCED_PATH_NETWORK, RESOURCED_INTERFACE_NETWORK, NULL, NULL },
46 /* Add new object & interface here*/
49 static Eina_List *edbus_handler_list;
50 static int edbus_init_val;
51 static E_DBus_Connection *edbus_conn;
52 static DBusPendingCall *edbus_request_name;
54 static int append_variant(DBusMessageIter *iter,
55 const char *sig, char *param[])
62 struct dbus_byte *byte;
67 for (ch = (char*)sig, i = 0; *ch != '\0'; ++i, ++ch) {
70 int_type = atoi(param[i]);
71 dbus_message_iter_append_basic(iter,
72 DBUS_TYPE_INT32, &int_type);
75 int_type = strtoul(param[i], NULL, 10);
76 dbus_message_iter_append_basic(iter,
77 DBUS_TYPE_UINT32, &int_type);
80 int64_type = atoll(param[i]);
81 dbus_message_iter_append_basic(iter,
82 DBUS_TYPE_UINT64, &int64_type);
85 dbus_message_iter_append_basic(iter,
86 DBUS_TYPE_STRING, ¶m[i]);
92 dbus_message_iter_open_container(iter,
93 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &arr);
94 byte = (struct dbus_byte*)param[i];
95 dbus_message_iter_append_fixed_array(&arr,
96 DBUS_TYPE_BYTE, &(byte->data), byte->size);
97 dbus_message_iter_close_container(iter, &arr);
104 dbus_message_iter_append_basic(iter,
105 DBUS_TYPE_INT32, ¶m[i]);
116 void serialize_params(char *params[], size_t n, ...)
121 for (i = 0; i < n; ++i) {
122 params[i] = va_arg(va, char *);
127 DBusMessage *dbus_method_sync(const char *dest, const char *path,
128 const char *interface, const char *method,
129 const char *sig, char *param[])
131 DBusConnection *conn;
133 DBusMessageIter iter;
138 conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
140 _E("dbus_bus_get error");
144 msg = dbus_message_new_method_call(dest, path, interface, method);
146 _E("dbus_message_new_method_call(%s:%s-%s)", path, interface, method);
150 dbus_message_iter_init_append(msg, &iter);
151 r = append_variant(&iter, sig, param);
153 _E("append_variant error(%d)", r);
154 dbus_message_unref(msg);
158 dbus_error_init(&err);
160 reply = dbus_connection_send_with_reply_and_block(conn, msg,
161 DBUS_REPLY_TIMEOUT, &err);
163 _E("dbus_connection_send error(No reply)");
166 if (dbus_error_is_set(&err)) {
167 _E("dbus_connection_send error(%s:%s)", err.name, err.message);
168 dbus_error_free(&err);
172 dbus_message_unref(msg);
176 int dbus_method_async(const char *dest, const char *path,
177 const char *interface, const char *method,
178 const char *sig, char *param[])
180 DBusConnection *conn;
182 DBusMessageIter iter;
185 conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
187 _E("dbus_bus_get error");
191 msg = dbus_message_new_method_call(dest, path, interface, method);
193 _E("dbus_message_new_method_call(%s:%s-%s)", path, interface, method);
197 dbus_message_iter_init_append(msg, &iter);
198 ret = append_variant(&iter, sig, param);
200 _E("append_variant error(%d)", ret);
201 dbus_message_unref(msg);
205 ret = dbus_connection_send(conn, msg, NULL);
206 dbus_message_unref(msg);
208 _E("dbus_connection_send error");
215 int register_edbus_interface(struct edbus_object *object)
217 int ret = RESOURCED_ERROR_FAIL;
220 _E("object is invalid value!");
224 object->obj = e_dbus_object_add(edbus_conn, object->path, NULL);
226 _E("fail to add edbus obj");
230 object->iface = e_dbus_interface_new(object->interface);
231 if (!object->iface) {
232 _E("fail to add edbus interface");
236 e_dbus_object_interface_attach(object->obj, object->iface);
241 E_DBus_Interface *get_edbus_interface(const char *path)
245 for (i = 0; i < ARRAY_SIZE(edbus_objects); i++)
246 if (!strcmp(path, edbus_objects[i].path))
247 return edbus_objects[i].iface;
252 pid_t get_edbus_sender_pid(DBusMessage *msg)
255 DBusMessage *send_msg;
256 DBusPendingCall *pending;
257 DBusMessageIter iter;
262 _E("invalid argument!");
263 return RESOURCED_ERROR_FAIL;
266 sender = dbus_message_get_sender(msg);
268 _E("invalid sender!");
269 return RESOURCED_ERROR_FAIL;
272 send_msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
275 "GetConnectionUnixProcessID");
277 _E("invalid send msg!");
278 return RESOURCED_ERROR_FAIL;
281 ret = dbus_message_append_args(send_msg, DBUS_TYPE_STRING,
282 &sender, DBUS_TYPE_INVALID);
284 _E("fail to append args!");
285 dbus_message_unref(send_msg);
286 return RESOURCED_ERROR_FAIL;
289 pending = e_dbus_message_send(edbus_conn, send_msg, NULL, -1, NULL);
291 _E("pending is null!");
292 dbus_message_unref(send_msg);
293 return RESOURCED_ERROR_FAIL;
296 dbus_message_unref(send_msg);
298 /* block until reply is received */
299 dbus_pending_call_block(pending);
301 msg = dbus_pending_call_steal_reply(pending);
302 dbus_pending_call_unref(pending);
304 _E("reply msg is null!");
305 return RESOURCED_ERROR_FAIL;
308 dbus_message_iter_init(msg, &iter);
309 dbus_message_iter_get_basic(&iter, &pid);
310 dbus_message_unref(msg);
315 static void unregister_edbus_signal_handle(void)
318 Eina_List *serach_next;
319 struct edbus_list *entry;
321 EINA_LIST_FOREACH_SAFE(edbus_handler_list, search, serach_next, entry) {
323 e_dbus_signal_handler_del(edbus_conn, entry->handler);
324 edbus_handler_list = eina_list_remove(edbus_handler_list, entry);
325 free(entry->signal_name);
331 int register_edbus_signal_handler(const char *path, const char *interface,
332 const char *name, E_DBus_Signal_Cb cb)
335 struct edbus_list *entry;
336 E_DBus_Signal_Handler *handler;
338 EINA_LIST_FOREACH(edbus_handler_list, search, entry) {
339 if (entry != NULL && strncmp(entry->signal_name, name, strlen(name)) == 0)
340 return RESOURCED_ERROR_FAIL;
343 handler = e_dbus_signal_handler_add(edbus_conn, NULL, path,
344 interface, name, cb, NULL);
347 _E("fail to add edbus handler");
348 return RESOURCED_ERROR_FAIL;
351 entry = malloc(sizeof(struct edbus_list));
355 return RESOURCED_ERROR_FAIL;
358 entry->signal_name = strndup(name, strlen(name));
360 if (!entry->signal_name) {
366 entry->handler = handler;
367 edbus_handler_list = eina_list_prepend(edbus_handler_list, entry);
368 if (!edbus_handler_list) {
369 _E("eina_list_prepend failed");
370 free(entry->signal_name);
372 return RESOURCED_ERROR_FAIL;
374 return RESOURCED_ERROR_NONE;
377 int broadcast_edbus_signal_str(const char *path, const char *interface,
378 const char *name, const char *sig, char *param[])
381 DBusConnection *conn;
382 DBusMessageIter iter;
385 conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
387 _E("dbus_bus_get error");
391 msg = dbus_message_new_signal(path, interface, name);
393 _E("fail to allocate new %s.%s signal", interface, name);
397 dbus_message_iter_init_append(msg, &iter);
398 r = append_variant(&iter, sig, param);
400 _E("append_variant error(%d)", r);
404 r = dbus_connection_send(conn, msg, NULL);
405 dbus_message_unref(msg);
408 _E("dbus_connection_send error(%s:%s-%s)",
409 path, interface, name);
413 return RESOURCED_ERROR_NONE;
416 int broadcast_edbus_signal(const char *path, const char *interface,
417 const char *name, int type, void *value)
419 DBusConnection *conn;
420 DBusMessage *msg = dbus_message_new_signal(path, interface, name);
423 conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
425 _E("dbus_bus_get error");
430 _E("fail to allocate new %s.%s signal", interface, name);
431 return RESOURCED_ERROR_FAIL;
434 dbus_message_append_args(msg, type, value, DBUS_TYPE_INVALID);
436 r = dbus_connection_send(conn, msg, NULL);
437 dbus_message_unref(msg);
440 _E("dbus_connection_send error(%s:%s-%s)",
441 path, interface, name);
445 return RESOURCED_ERROR_NONE;
448 resourced_ret_c edbus_add_methods(const char *path,
449 const struct edbus_method *const edbus_methods,
452 E_DBus_Interface *iface;
456 iface = get_edbus_interface(path);
459 _E("Fail to get edbus interface! Path = %s\n", path);
460 return RESOURCED_ERROR_FAIL;
463 for (i = 0; i < size; i++) {
464 ret = e_dbus_interface_method_add(iface,
465 edbus_methods[i].member,
466 edbus_methods[i].signature,
467 edbus_methods[i].reply_signature,
468 edbus_methods[i].func);
470 _E("Fail to add method %s!\n",
471 edbus_methods[i].member);
472 return RESOURCED_ERROR_FAIL;
476 return RESOURCED_ERROR_NONE;
479 static void request_name_cb(void *data, DBusMessage *msg, DBusError *error)
486 _D("invalid DBusMessage!");
490 dbus_error_init(&err);
491 r = dbus_message_get_args(msg, &err, DBUS_TYPE_UINT32, &val, DBUS_TYPE_INVALID);
493 _E("no message : [%s:%s]", err.name, err.message);
494 dbus_error_free(&err);
498 _I("Request Name reply : %d", val);
501 void edbus_init(void)
503 int retry = RESOURCED_ERROR_NONE;
506 edbus_init_val = e_dbus_init();
509 if (retry == EDBUS_INIT_RETRY_COUNT) {
510 _E("fail to init edbus");
518 edbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
520 goto retry_bus_request;
521 if (retry == EDBUS_INIT_RETRY_COUNT) {
522 _E("fail to get edbus");
530 edbus_request_name = e_dbus_request_name(edbus_conn, BUS_NAME,
531 DBUS_NAME_FLAG_REPLACE_EXISTING, request_name_cb, NULL);
532 if (edbus_request_name)
533 goto register_objects;
534 if (retry == EDBUS_INIT_RETRY_COUNT) {
535 _E("fail to request edbus name");
539 goto retry_bus_request;
542 for (i = 0; i < ARRAY_SIZE(edbus_objects); i++) {
545 ret = register_edbus_interface(&edbus_objects[i]);
547 _E("fail to add obj & interface for %s",
548 edbus_objects[i].interface);
552 _I("add new obj for %s", edbus_objects[i].interface);
555 _I("start edbus service");
558 void edbus_exit(void)
560 unregister_edbus_signal_handle();
561 e_dbus_connection_close(edbus_conn);