Update SMACK, Fix a crash of terminating sequence, etc, ...
[apps/livebox/data-provider-master.git] / src / client_life.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <errno.h>
19
20 #include <Eina.h>
21 #include <Ecore.h>
22
23 #include <dlog.h>
24 #include <packet.h>
25 #include <livebox-errno.h>
26
27 #include "client_life.h"
28 #include "instance.h"
29 #include "client_rpc.h"
30 #include "debug.h"
31 #include "util.h"
32 #include "slave_life.h"
33 #include "xmonitor.h"
34 #include "conf.h"
35
36 int errno;
37
38 static struct {
39         Eina_List *client_list;
40         int nr_of_paused_clients;
41
42         Eina_List *create_event_list;
43         Eina_List *destroy_event_list;
44 } s_info = {
45         .client_list = NULL,
46         .nr_of_paused_clients = 0,
47         .create_event_list = NULL,
48         .destroy_event_list = NULL,
49 };
50
51 struct subscribe_item {
52         char *cluster;
53         char *category;
54 };
55
56 struct global_event_handler {
57         void *cbdata;
58         int (*cb)(struct client_node *client, void *data);
59 };
60
61 struct data_item {
62         char *tag;
63         void *data;
64 };
65
66 struct event_item {
67         void *data;
68         int (*cb)(struct client_node *, void *);
69 };
70
71 struct client_node {
72         pid_t pid;
73         int refcnt;
74
75         int paused;
76
77         Eina_List *event_deactivate_list;
78         Eina_List *event_activate_list;
79         Eina_List *data_list;
80         Eina_List *subscribe_list;
81
82         int faulted;
83 };
84
85 static inline void invoke_global_destroyed_cb(struct client_node *client)
86 {
87         Eina_List *l;
88         Eina_List *n;
89         struct global_event_handler *item;
90
91         EINA_LIST_FOREACH_SAFE(s_info.destroy_event_list, l, n, item) {
92                 if (!item->cb) {
93                         ErrPrint("Callback function is not valid\n");
94                         continue;
95                 }
96
97                 if (item->cb(client, item->cbdata) < 0) {
98                         if (eina_list_data_find(s_info.destroy_event_list, item)) {
99                                 s_info.destroy_event_list = eina_list_remove(s_info.destroy_event_list, item);
100                                 DbgFree(item);
101                         }
102                 }
103         }
104 }
105
106 static inline void invoke_global_created_cb(struct client_node *client)
107 {
108         Eina_List *l;
109         Eina_List *n;
110         struct global_event_handler *item;
111
112         EINA_LIST_FOREACH_SAFE(s_info.create_event_list, l, n, item) {
113                 if (!item->cb) {
114                         ErrPrint("Callback function is not valid\n");
115                         continue;
116                 }
117
118                 if (item->cb(client, item->cbdata) < 0) {
119                         if (eina_list_data_find(s_info.create_event_list, item)) {
120                                 s_info.create_event_list = eina_list_remove(s_info.create_event_list, item);
121                                 DbgFree(item);
122                         }
123                 }
124         }
125 }
126
127 static inline void invoke_deactivated_cb(struct client_node *client)
128 {
129         struct event_item *item;
130         Eina_List *l;
131         Eina_List *n;
132         int ret;
133
134         client_ref(client); /*!< Prevent from client deletion in the callbacks */
135         EINA_LIST_FOREACH_SAFE(client->event_deactivate_list, l, n, item) {
136                 ret = item->cb(client, item->data);
137                 if (ret < 0) {
138                         if (eina_list_data_find(client->event_deactivate_list, item)) {
139                                 client->event_deactivate_list = eina_list_remove(client->event_deactivate_list, item);
140                                 DbgFree(item);
141                         }
142                 }
143         }
144         client_unref(client);
145 }
146
147 static inline void invoke_activated_cb(struct client_node *client)
148 {
149         struct event_item *item;
150         Eina_List *l;
151         Eina_List *n;
152         int ret;
153
154         client_ref(client); /*!< Prevent from client deletion in the callbacks */
155         EINA_LIST_FOREACH_SAFE(client->event_activate_list, l, n, item) {
156                 ret = item->cb(client, item->data);
157                 if (ret < 0) {
158                         if (eina_list_data_find(client->event_activate_list, item)) {
159                                 client->event_activate_list = eina_list_remove(client->event_activate_list, item);
160                                 DbgFree(item);
161                         }
162                 }
163         }
164         client_unref(client);
165 }
166
167 static inline void destroy_client_data(struct client_node *client)
168 {
169         struct event_item *event;
170         struct data_item *data;
171         struct subscribe_item *item;
172
173         DbgPrint("Client %p is destroyed\n", client);
174
175         invoke_global_destroyed_cb(client);
176         client_rpc_fini(client); /*!< Finalize the RPC after invoke destroy callbacks */
177
178         EINA_LIST_FREE(client->data_list, data) {
179                 DbgPrint("Tag is not cleared (%s)\n", data->tag);
180                 DbgFree(data->tag);
181                 DbgFree(data);
182         }
183
184         EINA_LIST_FREE(client->event_deactivate_list, event) {
185                 DbgFree(event);
186         }
187
188         EINA_LIST_FREE(client->subscribe_list, item) {
189                 DbgFree(item->cluster);
190                 DbgFree(item->category);
191                 DbgFree(item);
192         }
193
194         if (client->paused)
195                 s_info.nr_of_paused_clients--;
196
197         s_info.client_list = eina_list_remove(s_info.client_list, client);
198         DbgFree(client);
199
200         /*!
201          * \note
202          * If there is any changes of clients,
203          * We should check the pause/resume states again.
204          */
205         xmonitor_handle_state_changes();
206 }
207
208 static inline struct client_node *create_client_data(pid_t pid)
209 {
210         struct client_node *client;
211
212         client = calloc(1, sizeof(*client));
213         if (!client) {
214                 ErrPrint("Heap: %s\n", strerror(errno));
215                 return NULL;
216         }
217
218         client->pid = pid;
219         client->refcnt = 1;
220
221         s_info.client_list = eina_list_append(s_info.client_list, client);
222
223         /*!
224          * \note
225          * Right after create a client ADT,
226          * We assume that the client is paused.
227          */
228         client_paused(client);
229         xmonitor_handle_state_changes();
230         return client;
231 }
232
233 static Eina_Bool created_cb(void *data)
234 {
235         invoke_global_created_cb(data);
236         invoke_activated_cb(data);
237         /*!
238          * \note
239          * Client PAUSE/RESUME event must has to be sent after created event.
240          */
241         xmonitor_update_state(client_pid(data));
242         return ECORE_CALLBACK_CANCEL;
243 }
244
245 /*!
246  * \note
247  * Noramlly, client ADT is created when it send the "acquire" packet.
248  * It means we have the handle for communicating with the client already,
249  * So we just create its ADT in this function.
250  * And invoke the global created event & activated event callbacks
251  */
252 HAPI struct client_node *client_create(pid_t pid, int handle)
253 {
254         struct client_node *client;
255         int ret;
256
257         client = client_find_by_pid(pid);
258         if (client) {
259                 ErrPrint("Client %d is already exists\n", pid);
260                 return client;
261         }
262
263         client = create_client_data(pid);
264         if (!client) {
265                 ErrPrint("Failed to create a new client (%d)\n", pid);
266                 return NULL;
267         }
268
269         ret = client_rpc_init(client, handle);
270         if (ret < 0) {
271                 client = client_unref(client);
272                 ErrPrint("Failed to initialize the RPC for %d, Destroy client data %p(has to be 0x0)\n", pid, client);
273         } else {
274                 /*!
275                  * \note
276                  * To save the time to send reply packet to the client.
277                  */
278                 if (ecore_timer_add(DELAY_TIME, created_cb, client) == NULL) {
279                         ErrPrint("Failed to add a timer for client created event\n");
280                         client = client_unref(client);
281                         return NULL;
282                 }
283         }
284
285         return client;
286 }
287
288 HAPI struct client_node *client_ref(struct client_node *client)
289 {
290         if (!client)
291                 return NULL;
292
293         client->refcnt++;
294         return client;
295 }
296
297 HAPI struct client_node *client_unref(struct client_node *client)
298 {
299         if (!client)
300                 return NULL;
301
302         if (client->refcnt == 0) {
303                 ErrPrint("Client refcnt is not managed correctly\n");
304                 return NULL;
305         }
306
307         client->refcnt--;
308         if (client->refcnt == 0) {
309                 destroy_client_data(client);
310                 client = NULL;
311         }
312
313         return client;
314 }
315
316 HAPI const int const client_refcnt(const struct client_node *client)
317 {
318         return client->refcnt;
319 }
320
321 HAPI const pid_t const client_pid(const struct client_node *client)
322 {
323         return client ? client->pid : (pid_t)-1;
324 }
325
326 HAPI struct client_node *client_find_by_pid(pid_t pid)
327 {
328         Eina_List *l;
329         struct client_node *client;
330
331         EINA_LIST_FOREACH(s_info.client_list, l, client) {
332                 if (client->pid == pid)
333                         return client;
334         }
335
336         return NULL;
337 }
338
339 HAPI struct client_node *client_find_by_rpc_handle(int handle)
340 {
341         Eina_List *l;
342         struct client_node *client;
343
344         if (handle <= 0) {
345                 ErrPrint("Invalid handle %d\n", handle);
346                 return NULL;
347         }
348
349         EINA_LIST_FOREACH(s_info.client_list, l, client) {
350                 if (client_rpc_handle(client) == handle)
351                         return client;
352         }
353
354         return NULL;
355 }
356
357 HAPI const int const client_count_paused(void)
358 {
359         return s_info.nr_of_paused_clients;
360 }
361
362 HAPI int client_is_all_paused(void)
363 {
364         DbgPrint("%d, %d\n", eina_list_count(s_info.client_list), s_info.nr_of_paused_clients);
365         return eina_list_count(s_info.client_list) == s_info.nr_of_paused_clients;
366 }
367
368 HAPI int client_count(void)
369 {
370         return eina_list_count(s_info.client_list);
371 }
372
373 HAPI struct client_node *client_deactivated_by_fault(struct client_node *client)
374 {
375         if (!client || client->faulted)
376                 return client;
377
378         ErrPrint("Client[%p] is faulted(%d), pid(%d)\n", client, client->refcnt, client->pid);
379         client->faulted = 1;
380         client->pid = (pid_t)-1;
381
382         invoke_deactivated_cb(client);
383         client = client_destroy(client);
384         /*!
385          * \todo
386          * Who invokes this function has to care the reference counter of a client
387          * do I need to invoke the deactivated callback from here?
388          * client->pid = (pid_t)-1;
389          * slave_unref(client)
390          */
391         return client;
392 }
393
394 HAPI const int const client_is_faulted(const struct client_node *client)
395 {
396         /*!
397          * \note
398          * If the "client" is NIL, I assume that it is fault so returns TRUE(1)
399          */
400         return client ? client->faulted : 1;
401 }
402
403 HAPI void client_reset_fault(struct client_node *client)
404 {
405         if (client)
406                 client->faulted = 0;
407 }
408
409 HAPI int client_event_callback_add(struct client_node *client, enum client_event event, int (*cb)(struct client_node *, void *), void *data)
410 {
411         struct event_item *item;
412
413         if (!cb) {
414                 ErrPrint("Invalid callback (cb == NULL)\n");
415                 return LB_STATUS_ERROR_INVALID;
416         }
417
418         item = calloc(1, sizeof(*item));
419         if (!item) {
420                 ErrPrint("Heap: %s\n", strerror(errno));
421                 return LB_STATUS_ERROR_MEMORY;
422         }
423
424         item->cb = cb;
425         item->data = data;
426
427         /*!
428          * \note
429          * Use the eina_list_prepend API.
430          * To keep the sequence of a callback invocation.
431          *
432          * Here is an example sequence.
433          *
434          * client_event_callback_add(CALLBACK_01);
435          * client_event_callback_add(CALLBACK_02);
436          * client_event_callback_add(CALLBACK_03);
437          *
438          * Then the invoke_event_callback function will call the CALLBACKS as below sequence
439          *
440          * invoke_CALLBACK_03
441          * invoke_CALLBACK_02
442          * invoke_CALLBACK_01
443          */
444
445         switch (event) {
446         case CLIENT_EVENT_DEACTIVATE:
447                 client->event_deactivate_list = eina_list_prepend(client->event_deactivate_list, item);
448                 break;
449         case CLIENT_EVENT_ACTIVATE:
450                 client->event_activate_list = eina_list_prepend(client->event_activate_list, item);
451                 break;
452         default:
453                 DbgFree(item);
454                 return LB_STATUS_ERROR_INVALID;
455         }
456
457         return LB_STATUS_SUCCESS;
458 }
459
460 HAPI int client_event_callback_del(struct client_node *client, enum client_event event, int (*cb)(struct client_node *, void *), void *data)
461 {
462         struct event_item *item;
463         Eina_List *l;
464         Eina_List *n;
465
466         if (!cb) {
467                 ErrPrint("Invalid callback (cb == NULL)\n");
468                 return LB_STATUS_ERROR_INVALID;
469         }
470
471         switch (event) {
472         case CLIENT_EVENT_DEACTIVATE:
473                 EINA_LIST_FOREACH_SAFE(client->event_deactivate_list, l, n, item) {
474                         if (item->cb == cb && item->data == data) {
475                                 client->event_deactivate_list = eina_list_remove(client->event_deactivate_list, item);
476                                 DbgFree(item);
477                                 return LB_STATUS_SUCCESS;
478                         }
479                 }
480                 break;
481
482         case CLIENT_EVENT_ACTIVATE:
483                 EINA_LIST_FOREACH_SAFE(client->event_activate_list, l, n, item) {
484                         if (item->cb == cb && item->data == data) {
485                                 client->event_activate_list = eina_list_remove(client->event_activate_list, item);
486                                 DbgFree(item);
487                                 return LB_STATUS_SUCCESS;
488                         }
489                 }
490                 break;
491
492         default:
493                 ErrPrint("Invalid event\n");
494                 break;
495         }
496
497         return LB_STATUS_ERROR_NOT_EXIST;
498 }
499
500 HAPI int client_set_data(struct client_node *client, const char *tag, void *data)
501 {
502         struct data_item *item;
503
504         item = calloc(1, sizeof(*item));
505         if (!item) {
506                 ErrPrint("Heap: %s\n", strerror(errno));
507                 return LB_STATUS_ERROR_MEMORY;
508         }
509
510         item->tag = strdup(tag);
511         if (!item->tag) {
512                 ErrPrint("Heap: %s\n", strerror(errno));
513                 DbgFree(item);
514                 return LB_STATUS_ERROR_MEMORY;
515         }
516
517         item->data = data;
518
519         client->data_list = eina_list_append(client->data_list, item);
520         return LB_STATUS_SUCCESS;
521 }
522
523 HAPI void *client_data(struct client_node *client, const char *tag)
524 {
525         Eina_List *l;
526         struct data_item *item;
527
528         EINA_LIST_FOREACH(client->data_list, l, item) {
529                 if (!strcmp(item->tag, tag))
530                         return item->data;
531         }
532
533         return NULL;
534 }
535
536 HAPI void *client_del_data(struct client_node *client, const char *tag)
537 {
538         Eina_List *l;
539         Eina_List *n;
540         struct data_item *item;
541
542         EINA_LIST_FOREACH_SAFE(client->data_list, l, n, item) {
543                 if (!strcmp(item->tag, tag)) {
544                         void *data;
545                         client->data_list = eina_list_remove(client->data_list, item);
546                         data = item->data;
547                         DbgFree(item->tag);
548                         DbgFree(item);
549                         return data;
550                 }
551         }
552
553         return NULL;
554 }
555
556 HAPI void client_paused(struct client_node *client)
557 {
558         if (client->paused)
559                 return;
560
561         client->paused = 1;
562         s_info.nr_of_paused_clients++;
563 }
564
565 HAPI void client_resumed(struct client_node *client)
566 {
567         if (client->paused == 0)
568                 return;
569
570         client->paused = 0;
571         s_info.nr_of_paused_clients--;
572 }
573
574 HAPI int client_init(void)
575 {
576         return LB_STATUS_SUCCESS;
577 }
578
579 HAPI void client_fini(void)
580 {
581         struct global_event_handler *handler;
582         struct client_node *client;
583         Eina_List *l;
584         Eina_List *n;
585
586         EINA_LIST_FOREACH_SAFE(s_info.client_list, l, n, client) {
587                 (void)client_destroy(client);
588         }
589
590         EINA_LIST_FREE(s_info.create_event_list, handler) {
591                 DbgFree(handler);
592         }
593
594         EINA_LIST_FREE(s_info.destroy_event_list, handler) {
595                 DbgFree(handler);
596         }
597 }
598
599 HAPI const int const client_is_activated(const struct client_node *client)
600 {
601         return client ? (client->pid != (pid_t)-1) : 1;
602 }
603
604 HAPI int client_global_event_handler_add(enum client_global_event event_type, int (*cb)(struct client_node *client, void *data), void *data)
605 {
606         struct global_event_handler *handler;
607
608         handler = malloc(sizeof(*handler));
609         if (!handler) {
610                 ErrPrint("Heap: %s\n", strerror(errno));
611                 return LB_STATUS_ERROR_MEMORY;
612         }
613
614         handler->cbdata = data;
615         handler->cb = cb;
616
617         switch (event_type) {
618         case CLIENT_GLOBAL_EVENT_CREATE:
619                 s_info.create_event_list = eina_list_prepend(s_info.create_event_list, handler);
620                 break;
621         case CLIENT_GLOBAL_EVENT_DESTROY:
622                 s_info.destroy_event_list = eina_list_prepend(s_info.destroy_event_list, handler);
623                 break;
624         default:
625                 DbgFree(handler);
626                 return LB_STATUS_ERROR_INVALID;
627         }
628
629         return LB_STATUS_SUCCESS;
630 }
631
632 HAPI int client_global_event_handler_del(enum client_global_event event_type, int (*cb)(struct client_node *, void *), void *data)
633 {
634         Eina_List *l;
635         Eina_List *n;
636         struct global_event_handler *handler;
637
638         switch (event_type) {
639         case CLIENT_GLOBAL_EVENT_CREATE:
640                 EINA_LIST_FOREACH_SAFE(s_info.create_event_list, l, n, handler) {
641                         if (handler->cb == cb && handler->cbdata == data) {
642                                 s_info.create_event_list = eina_list_remove(s_info.create_event_list, handler);
643                                 DbgFree(handler);
644                                 return LB_STATUS_SUCCESS;
645                         }
646                 }
647                 break;
648         case CLIENT_GLOBAL_EVENT_DESTROY:
649                 EINA_LIST_FOREACH_SAFE(s_info.destroy_event_list, l, n, handler) {
650                         if (handler->cb == cb && handler->cbdata == data) {
651                                 s_info.destroy_event_list = eina_list_remove(s_info.destroy_event_list, handler);
652                                 DbgFree(handler);
653                                 return LB_STATUS_SUCCESS;
654                         }
655                 }
656                 break;
657         default:
658                 break;
659         }
660
661         return LB_STATUS_ERROR_NOT_EXIST;
662 }
663
664 HAPI int client_subscribe(struct client_node *client, const char *cluster, const char *category)
665 {
666         struct subscribe_item *item;
667
668         item = malloc(sizeof(*item));
669         if (!item) {
670                 ErrPrint("Heap: %s\n", strerror(errno));
671                 return LB_STATUS_ERROR_MEMORY;
672         }
673
674         item->cluster = strdup(cluster);
675         if (!item->cluster) {
676                 ErrPrint("Heap: %s\n", strerror(errno));
677                 DbgFree(item);
678                 return LB_STATUS_ERROR_MEMORY;
679         }
680
681         item->category = strdup(category);
682         if (!item->category) {
683                 ErrPrint("Heap: %s\n", strerror(errno));
684                 DbgFree(item->cluster);
685                 DbgFree(item);
686                 return LB_STATUS_ERROR_MEMORY;
687         }
688
689         client->subscribe_list = eina_list_append(client->subscribe_list, item);
690         return LB_STATUS_SUCCESS;
691 }
692
693 HAPI int client_unsubscribe(struct client_node *client, const char *cluster, const char *category)
694 {
695         struct subscribe_item *item;
696         Eina_List *l;
697         Eina_List *n;
698
699         EINA_LIST_FOREACH_SAFE(client->subscribe_list, l, n, item) {
700                 if (!strcasecmp(cluster, item->cluster) && !strcasecmp(category, item->category)) {
701                         client->subscribe_list = eina_list_remove(client->subscribe_list, item);
702                         DbgFree(item->cluster);
703                         DbgFree(item->category);
704                         DbgFree(item);
705                         return LB_STATUS_SUCCESS;
706                 }
707         }
708
709         return LB_STATUS_ERROR_NOT_EXIST;
710 }
711
712 HAPI int client_is_subscribed(struct client_node *client, const char *cluster, const char *category)
713 {
714         struct subscribe_item *item;
715         Eina_List *l;
716
717         EINA_LIST_FOREACH(client->subscribe_list, l, item) {
718                 if (!strcmp(item->cluster, "*"))
719                         return 1;
720
721                 if (strcasecmp(item->cluster, cluster))
722                         continue;
723
724                 if (!strcmp(item->category, "*"))
725                         return 1;
726
727                 if (!strcasecmp(item->category, category))
728                         return 1;
729         }
730
731         return 0;
732 }
733
734 HAPI int client_browse_list(const char *cluster, const char *category, int (*cb)(struct client_node *client, void *data), void *data)
735 {
736         Eina_List *l;
737         struct client_node *client;
738         int cnt;
739
740         if (!cb || !cluster || !category)
741                 return LB_STATUS_ERROR_INVALID;
742
743         cnt = 0;
744         EINA_LIST_FOREACH(s_info.client_list, l, client) {
745                 if (!client_is_subscribed(client, cluster, category))
746                         continue;
747
748                 if (cb(client, data) < 0)
749                         return LB_STATUS_ERROR_CANCEL;
750
751                 cnt++;
752         }
753
754         return cnt;
755 }
756
757 HAPI int client_nr_of_subscriber(const char *cluster, const char *category)
758 {
759         Eina_List *l;
760         struct client_node *client;
761         int cnt;
762
763         cnt = 0;
764         EINA_LIST_FOREACH(s_info.client_list, l, client) {
765                 cnt += !!client_is_subscribed(client, cluster, category);
766         }
767
768         return cnt;
769 }
770
771 HAPI int client_broadcast(struct inst_info *inst, struct packet *packet)
772 {
773         Eina_List *l;
774         Eina_List *list;
775         struct client_node *client;
776
777         list = inst ? instance_client_list(inst) : s_info.client_list;
778         EINA_LIST_FOREACH(list, l, client) {
779                 if (client_pid(client) < 0) {
780                         ErrPrint("Client[%p] has PID[%d]\n", client, client_pid(client));
781                         continue;
782                 }
783
784                 (void)client_rpc_async_request(client, packet_ref(packet));
785         }
786
787         packet_unref(packet);
788         return LB_STATUS_SUCCESS;
789 }
790
791 /* End of a file */