Initialize Tizen 2.3
[framework/system/coord.git] / src / core / edbus-handler.c
1 /*
2  * coord
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19
20 #include <stdbool.h>
21 #include "core/log.h"
22 #include "core/edbus-handler.h"
23 #include "core/common.h"
24 #include "core/list.h"
25
26 #define EDBUS_INIT_RETRY_COUNT 5
27
28 /* -1 is a default timeout value, it's converted to 25*1000 internally. */
29 #define DBUS_REPLY_TIMEOUT      (-1)
30 #define RETRY_MAX 5
31
32 struct edbus_list{
33         char *signal_name;
34         char *interface_name;
35         E_DBus_Signal_Cb cb;
36         E_DBus_Signal_Handler *handler;
37 };
38
39 static struct edbus_object {
40         const char *path;
41         const char *interface;
42         E_DBus_Object *obj;
43         E_DBus_Interface *iface;
44 } edbus_objects[] = {
45         { COORD_PATH_ROTATION   , COORD_INTERFACE_ROTATION      , NULL, NULL },
46         /* Add new object & interface here*/
47 };
48
49 static c_list *edbus_handler_list;
50 static int edbus_init_val;
51 static DBusConnection *conn;
52 static E_DBus_Connection *edbus_conn;
53 static DBusPendingCall *edbus_request_name;
54
55 static int register_edbus_interface(struct edbus_object *object)
56 {
57         int ret;
58
59         if (!object) {
60                 _E("object is invalid value!");
61                 return -1;
62         }
63
64         object->obj = e_dbus_object_add(edbus_conn, object->path, NULL);
65         if (!object->obj) {
66                 _E("fail to add edbus obj");
67                 return -1;
68         }
69
70         object->iface = e_dbus_interface_new(object->interface);
71         if (!object->iface) {
72                 _E("fail to add edbus interface");
73                 e_dbus_object_free(object->obj);
74                 object->obj = NULL;
75                 return -1;
76         }
77
78         e_dbus_object_interface_attach(object->obj, object->iface);
79
80         return 0;
81 }
82
83 static int unregister_edbus_interface(struct edbus_object *object)
84 {
85         int ret;
86
87         if (!object) {
88                 _E("object is invalid value!");
89                 return -1;
90         }
91
92         if (object->iface) {
93                 e_dbus_object_interface_detach(object->obj, object->iface);
94                 e_dbus_interface_unref(object->iface);
95                 object->iface = NULL;
96         }
97
98         if (object->obj) {
99                 e_dbus_object_free(object->obj);
100                 object->obj = NULL;
101         }
102
103         return 0;
104 }
105
106 E_DBus_Interface *get_edbus_interface(const char *path)
107 {
108         int i;
109
110         for (i = 0; i < ARRAY_SIZE(edbus_objects); i++)
111                 if (!strcmp(path, edbus_objects[i].path))
112                         return edbus_objects[i].iface;
113
114         return NULL;
115 }
116
117 pid_t get_edbus_sender_pid(DBusMessage *msg)
118 {
119         const char *sender;
120         DBusMessage *send_msg;
121         DBusPendingCall *pending;
122         DBusMessageIter iter;
123         int ret;
124         pid_t pid;
125
126         if (!msg) {
127                 _E("invalid argument!");
128                 return -1;
129         }
130
131         sender = dbus_message_get_sender(msg);
132         if (!sender) {
133                 _E("invalid sender!");
134                 return -1;
135         }
136
137         send_msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
138                                     DBUS_PATH_DBUS,
139                                     DBUS_INTERFACE_DBUS,
140                                     "GetConnectionUnixProcessID");
141         if (!send_msg) {
142                 _E("invalid send msg!");
143                 return -1;
144         }
145
146         ret = dbus_message_append_args(send_msg, DBUS_TYPE_STRING,
147                                     &sender, DBUS_TYPE_INVALID);
148         if (!ret) {
149                 _E("fail to append args!");
150                 dbus_message_unref(send_msg);
151                 return -1;
152         }
153
154         pending = e_dbus_message_send(edbus_conn, send_msg, NULL, -1, NULL);
155         if (!pending) {
156                 _E("pending is null!");
157                 dbus_message_unref(send_msg);
158                 return -1;
159         }
160
161         dbus_message_unref(send_msg);
162
163         /* block until reply is received */
164         dbus_pending_call_block(pending);
165
166         msg = dbus_pending_call_steal_reply(pending);
167         dbus_pending_call_unref(pending);
168         if (!msg) {
169                 _E("reply msg is null!");
170                 return -1;
171         }
172
173         dbus_message_iter_init(msg, &iter);
174         dbus_message_iter_get_basic(&iter, &pid);
175         dbus_message_unref(msg);
176
177         return pid;
178 }
179
180 static void unregister_edbus_signal_handle(void)
181 {
182         c_list *tmp;
183         struct edbus_list *entry;
184
185         C_LIST_FOREACH(edbus_handler_list, tmp, entry) {
186                 if (entry != NULL) {
187                         e_dbus_signal_handler_del(edbus_conn, entry->handler);
188                         C_LIST_REMOVE(edbus_handler_list, entry);
189                         free(entry->signal_name);
190                         free(entry);
191                 }
192         }
193 }
194
195 int unregister_edbus_signal_handler(const char *interface, const char *name, E_DBus_Signal_Cb cb)
196 {
197         c_list *tmp;
198         struct edbus_list *entry;
199         E_DBus_Signal_Handler *handler;
200
201         C_LIST_FOREACH(edbus_handler_list, tmp, entry) {
202                 if (entry != NULL && strncmp(entry->signal_name, name, strlen(name)) == 0
203                                         && strncmp(entry->interface_name, interface, strlen(interface)) == 0
204                                         && entry->cb == cb) {
205                         e_dbus_signal_handler_del(edbus_conn, entry->handler);
206                         C_LIST_REMOVE(edbus_handler_list, entry);
207                         free(entry->signal_name);
208                         free(entry->interface_name);
209                         free(entry);
210                         return 0;
211                 }
212         }
213
214         return -ENOENT;
215 }
216
217 int register_edbus_signal_handler(const char *path, const char *interface,
218                 const char *name, E_DBus_Signal_Cb cb)
219 {
220         c_list *tmp;
221         struct edbus_list *entry;
222         E_DBus_Signal_Handler *handler;
223
224         C_LIST_FOREACH(edbus_handler_list, tmp, entry) {
225                 if (entry != NULL && strncmp(entry->signal_name, name, strlen(name)) == 0
226                                         && entry->cb == cb)
227                         return -EEXIST;
228         }
229
230         handler = e_dbus_signal_handler_add(edbus_conn, NULL, path,
231                                 interface, name, cb, NULL);
232
233         if (!handler) {
234                 _E("fail to add edbus handler");
235                 return -ENOMEM;
236         }
237
238         entry = malloc(sizeof(struct edbus_list));
239
240         if (!entry) {
241                 _E("Malloc failed");
242                 return -ENOMEM;
243         }
244
245         entry->signal_name = strndup(name, strlen(name));
246
247         if (!entry->signal_name) {
248                 _E("Malloc failed");
249                 free(entry);
250                 return -ENOMEM;
251         }
252
253         entry->interface_name = strndup(interface, strlen(interface));
254
255         if (!entry->interface_name) {
256                 _E("Malloc failed");
257                 free(entry->signal_name);
258                 free(entry);
259                 return -ENOMEM;
260         }
261
262         entry->handler = handler;
263         entry->cb = cb;
264         C_LIST_PREPEND(edbus_handler_list, entry);
265         if (!edbus_handler_list) {
266                 _E("eina_list_prepend failed");
267                 free(entry->signal_name);
268                 free(entry->interface_name);
269                 free(entry);
270                 return -ENOMEM;
271         }
272         return 0;
273 }
274
275 int broadcast_edbus_signal(const char *path, const char *interface,
276                 const char *name, const char *sig, char *param[])
277 {
278         DBusMessage *msg;
279         DBusMessageIter iter;
280         int r;
281
282         msg = dbus_message_new_signal(path, interface, name);
283         if (!msg) {
284                 _E("fail to allocate new %s.%s signal", interface, name);
285                 return -EPERM;
286         }
287
288         dbus_message_iter_init_append(msg, &iter);
289         r = append_variant(&iter, sig, param);
290         if (r < 0) {
291                 _E("append_variant error(%d)", r);
292                 return -EPERM;
293         }
294
295         e_dbus_message_send(edbus_conn, msg, NULL, -1, NULL);
296
297         dbus_message_unref(msg);
298         return 0;
299 }
300
301 int send_edbus_message(const char* dest, const char *path, const char *interface,
302                 const char *method, const char *sig, char *param[])
303 {
304         DBusMessage *msg;
305         DBusMessageIter iter;
306         int r;
307
308         msg = dbus_message_new_method_call(dest, path, interface, method);
309         if (!msg) {
310                 _E("fail to allocate new %s.%s message", interface, method);
311                 return -EPERM;
312         }
313
314         dbus_message_iter_init_append(msg, &iter);
315         r = append_variant(&iter, sig, param);
316         if (r < 0) {
317                 _E("append_variant error(%d)", r);
318                 return -EPERM;
319         }
320
321         e_dbus_message_send(edbus_conn, msg, NULL, -1, NULL);
322
323         dbus_message_unref(msg);
324         return 0;
325 }
326
327 void register_edbus_method_handler(const char* dest, const char* path, const char* interface,
328                 const char* method, E_DBus_Method_Return_Cb cb)
329 {
330         DBusMessage *msg = NULL;
331
332         msg = dbus_message_new_method_call(dest, path, interface, method);
333         if (!msg) {
334                 _E("Failed: dbus_message_new_method_call()");
335         }
336
337         e_dbus_message_send(edbus_conn, msg, cb, DBUS_REPLY_TIMEOUT, NULL);
338
339         dbus_message_unref(msg);
340 }
341
342 int register_edbus_method(const char *path, const struct edbus_method *edbus_methods, int size)
343 {
344         E_DBus_Interface *iface;
345         int ret;
346         int i;
347
348         iface = get_edbus_interface(path);
349
350         if (!iface) {
351                 _E("fail to get edbus interface!");
352                 return -ENODEV;
353         }
354
355         for (i = 0; i < size; i++) {
356                 ret = e_dbus_interface_method_add(iface,
357                                     edbus_methods[i].member,
358                                     edbus_methods[i].signature,
359                                     edbus_methods[i].reply_signature,
360                                     edbus_methods[i].func);
361                 if (!ret) {
362                         _E("fail to add method %s!", edbus_methods[i].member);
363                         return -EINVAL;
364                 }
365         }
366
367         return 0;
368 }
369
370 static void request_name_cb(void *data, DBusMessage *msg, DBusError *error)
371 {
372         DBusError err;
373         unsigned int val;
374         int r;
375
376         if (!msg) {
377                 _D("invalid DBusMessage!");
378                 return;
379         }
380
381         dbus_error_init(&err);
382         r = dbus_message_get_args(msg, &err, DBUS_TYPE_UINT32, &val, DBUS_TYPE_INVALID);
383         if (!r) {
384                 _E("no message : [%s:%s]", err.name, err.message);
385                 dbus_error_free(&err);
386                 return;
387         }
388
389         _I("Request Name reply : %d", val);
390 }
391
392 void edbus_init(void *data)
393 {
394         DBusError error;
395         int retry = 0;
396         int i, ret;
397
398         dbus_threads_init_default();
399         dbus_error_init(&error);
400
401         do {
402                 edbus_init_val = e_dbus_init();
403                 if (edbus_init_val)
404                         break;
405                 if (retry == EDBUS_INIT_RETRY_COUNT) {
406                         _E("fail to init edbus");
407                         return;
408                 }
409                 retry++;
410         } while (retry <= EDBUS_INIT_RETRY_COUNT);
411
412         retry = 0;
413         do {
414                 edbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
415                 if (edbus_conn)
416                         break;
417                 if (retry == EDBUS_INIT_RETRY_COUNT) {
418                         _E("fail to get edbus");
419                         return;
420                 }
421                 retry++;
422         } while (retry <= EDBUS_INIT_RETRY_COUNT);
423
424         retry = 0;
425         do {
426                 edbus_request_name = e_dbus_request_name(edbus_conn, COORD_BUS_NAME,
427                                 DBUS_NAME_FLAG_REPLACE_EXISTING, request_name_cb, NULL);
428                 if (edbus_request_name)
429                         break;
430                 if (retry == EDBUS_INIT_RETRY_COUNT) {
431                         _E("fail to request edbus name");
432                         goto out1;
433                 }
434                 retry++;
435         } while (retry <= EDBUS_INIT_RETRY_COUNT);
436
437         for (i = 0; i < ARRAY_SIZE(edbus_objects); i++) {
438                 ret = register_edbus_interface(&edbus_objects[i]);
439                 if (ret < 0) {
440                         _E("fail to add obj & interface for %s",
441                                     edbus_objects[i].interface);
442                         goto out2;
443                 }
444                 _D("add new obj for %s", edbus_objects[i].interface);
445         }
446         return;
447
448 out2:
449         e_dbus_release_name(edbus_conn, COORD_BUS_NAME, request_name_cb, NULL);
450 out1:
451         e_dbus_connection_close(edbus_conn);
452         edbus_conn = NULL;
453         e_dbus_shutdown();
454 }
455
456 void edbus_exit(void *data)
457 {
458         if(!edbus_conn)
459                 return;
460
461         int i, ret;
462
463         unregister_edbus_signal_handle();
464
465         for (i = 0; i < ARRAY_SIZE(edbus_objects); i++) {
466                 ret = unregister_edbus_interface(&edbus_objects[i]);
467                 if (ret < 0) {
468                         _E("fail to delete obj & interface for %s",
469                                     edbus_objects[i].interface);
470                 }
471                 _D("add new obj for %s", edbus_objects[i].interface);
472         }
473
474         e_dbus_release_name(edbus_conn, COORD_BUS_NAME, request_name_cb, NULL);
475
476         e_dbus_connection_close(edbus_conn);
477         edbus_conn = NULL;
478
479         e_dbus_shutdown();
480 }