tizen 2.3 release
[apps/livebox/data-provider-master.git] / src / service_common.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 #define _GNU_SOURCE
17 #include <stdio.h>
18 #include <pthread.h>
19 #include <secure_socket.h>
20 #include <packet.h>
21 #include <errno.h>
22 #include <sys/time.h>
23 #include <sys/types.h>
24 #include <sys/timerfd.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <time.h>
28
29 #include <dlog.h>
30 #include <Eina.h>
31 #include <com-core.h>
32 #if defined(HAVE_LIVEBOX)
33 #include <dynamicbox_errno.h>
34 #else
35 #include <lite-errno.h>
36 #endif
37
38 #include "service_common.h"
39 #include "util.h"
40 #include "debug.h"
41 #include "conf.h"
42
43 #define EVT_CH          'e'
44 #define EVT_END_CH      'x'
45 #define DEFAULT_TIMEOUT 2.0f
46
47 int errno;
48
49 struct service_event_item {
50         enum {
51                 SERVICE_EVENT_TIMER
52         } type;
53
54         union {
55                 struct {
56                         int fd;
57                 } timer;
58         } info;
59
60         int (*event_cb)(struct service_context *svc_cx, void *data);
61         void *cbdata;
62 };
63
64 struct tcb_event_cbdata {
65         struct tcb *tcb;
66         void (*cb)(struct service_context *svc_ctx, struct tcb *tcb, void *data);
67         void *data;
68 };
69
70 /*!
71  * \note
72  * Server information and global (only in this file-scope) variables are defined
73  */
74 struct service_context {
75         pthread_t server_thid; /*!< Server thread Id */
76         int fd; /*!< Server socket handle */
77
78         Eina_List *tcb_list; /*!< TCB list, list of every thread for client connections */
79         pthread_mutex_t tcb_list_lock;
80
81         Eina_List *packet_list;
82         pthread_mutex_t packet_list_lock;
83         int evt_pipe[PIPE_MAX];
84         int tcb_pipe[PIPE_MAX];
85
86         int (*service_thread_main)(struct tcb *tcb, struct packet *packet, void *data);
87         void *service_thread_data;
88
89         Eina_List *event_list;
90
91         Eina_List *tcb_create_cb_list;
92         Eina_List *tcb_destroy_cb_list;
93 };
94
95 struct packet_info {
96         struct tcb *tcb;
97         struct packet *packet;
98 };
99
100 /*!
101  * \note
102  * Thread Control Block
103  * - The main server will create a thread for every client connections.
104  *   When a new client is comming to us, this TCB block will be allocated and initialized.
105  */
106 struct tcb { /* Thread controll block */
107         struct service_context *svc_ctx;
108         pthread_t thid; /*!< Thread Id */
109         int fd; /*!< Connection handle */
110         enum tcb_type type;
111         int ctrl_pipe[PIPE_MAX];
112         pid_t pid; /*!< Keep the PID of client, if the client is remote one, this will be -1 */
113 };
114
115 /*!
116  * Do services for clients
117  * Routing packets to destination processes.
118  * CLIENT THREAD
119  */
120 static void *client_packet_pump_main(void *data)
121 {
122         struct tcb *tcb = data;
123         struct service_context *svc_ctx = tcb->svc_ctx;
124         struct packet *packet = NULL;
125         fd_set set;
126         char *ptr = NULL;
127         int size = 0;
128         int packet_offset = 0;
129         int recv_offset = 0;
130         long ret;
131         int fd;
132         char evt_ch = EVT_CH;
133         enum {
134                 RECV_INIT,
135                 RECV_HEADER,
136                 RECV_PAYLOAD,
137                 RECV_DONE,
138         } recv_state;
139         struct packet_info *packet_info;
140         Eina_List *l;
141
142         ret = 0;
143         recv_state = RECV_INIT;
144         /*!
145          * \note
146          * To escape from the switch statement, we use this ret value
147          */
148         while (ret == 0) {
149                 FD_ZERO(&set);
150                 FD_SET(tcb->fd, &set);
151                 FD_SET(tcb->ctrl_pipe[PIPE_READ], &set);
152                 fd = tcb->fd > tcb->ctrl_pipe[PIPE_READ] ? tcb->fd : tcb->ctrl_pipe[PIPE_READ];
153                 ret = select(fd + 1, &set, NULL, NULL, NULL);
154                 if (ret < 0) {
155                         ret = -errno;
156                         if (errno == EINTR) {
157                                 ErrPrint("INTERRUPTED\n");
158                                 ret = 0;
159                                 continue;
160                         }
161                         ErrPrint("Error: %s\n", strerror(errno));
162                         DbgFree(ptr);
163                         ptr = NULL;
164                         break;
165                 } else if (ret == 0) {
166                         ErrPrint("Timeout\n");
167                         ret = -ETIMEDOUT;
168                         DbgFree(ptr);
169                         ptr = NULL;
170                         break;
171                 }
172
173                 if (FD_ISSET(tcb->ctrl_pipe[PIPE_READ], &set)) {
174                         DbgPrint("Thread is canceled\n");
175                         ret = -ECANCELED;
176                         DbgFree(ptr);
177                         ptr = NULL;
178                         break;
179                 }
180
181                 if (!FD_ISSET(tcb->fd, &set)) {
182                         ErrPrint("Unexpected handler is toggled\n");
183                         ret = -EINVAL;
184                         DbgFree(ptr);
185                         ptr = NULL;
186                         break;
187                 }
188
189                 /*!
190                  * \TODO
191                  * Service!!! Receive packet & route packet
192                  */
193                 switch (recv_state) {
194                 case RECV_INIT:
195                         size = packet_header_size();
196                         packet_offset = 0;
197                         recv_offset = 0;
198                         packet = NULL;
199                         ptr = malloc(size);
200                         if (!ptr) {
201                                 ErrPrint("Heap: %s\n", strerror(errno));
202                                 ret = -ENOMEM;
203                                 break;
204                         }
205                         recv_state = RECV_HEADER;
206                         /* Go through, don't break from here */
207                 case RECV_HEADER:
208                         ret = secure_socket_recv(tcb->fd, ptr, size - recv_offset, &tcb->pid);
209                         if (ret <= 0) {
210                                 if (ret == 0) {
211                                         ret = -ECANCELED;
212                                 }
213                                 DbgFree(ptr);
214                                 ptr = NULL;
215                                 break;
216                         }
217
218                         recv_offset += ret;
219                         ret = 0;
220
221                         if (recv_offset == size) {
222                                 packet = packet_build(packet, packet_offset, ptr, size);
223                                 DbgFree(ptr);
224                                 ptr = NULL;
225                                 if (!packet) {
226                                         ret = -EFAULT;
227                                         break;
228                                 }
229
230                                 packet_offset += recv_offset;
231
232                                 size = packet_payload_size(packet);
233                                 if (size <= 0) {
234                                         recv_state = RECV_DONE;
235                                         recv_offset = 0;
236                                         break;
237                                 }
238
239                                 recv_state = RECV_PAYLOAD;
240                                 recv_offset = 0;
241
242                                 ptr = malloc(size);
243                                 if (!ptr) {
244                                         ErrPrint("Heap: %s\n", strerror(errno));
245                                         ret = -ENOMEM;
246                                 }
247                         }
248                         break;
249                 case RECV_PAYLOAD:
250                         ret = secure_socket_recv(tcb->fd, ptr, size - recv_offset, &tcb->pid);
251                         if (ret <= 0) {
252                                 if (ret == 0) {
253                                         ret = -ECANCELED;
254                                 }
255                                 DbgFree(ptr);
256                                 ptr = NULL;
257                                 break;
258                         }
259
260                         recv_offset += ret;
261                         ret = 0;
262
263                         if (recv_offset == size) {
264                                 packet = packet_build(packet, packet_offset, ptr, size);
265                                 DbgFree(ptr);
266                                 ptr = NULL;
267                                 if (!packet) {
268                                         ret = -EFAULT;
269                                         break;
270                                 }
271
272                                 packet_offset += recv_offset;
273
274                                 recv_state = RECV_DONE;
275                                 recv_offset = 0;
276                         }
277                         break;
278                 case RECV_DONE:
279                 default:
280                         /* Dead code */
281                         break;
282                 }
283
284                 if (recv_state == RECV_DONE) {
285                         /*!
286                          * Push this packet to the packet list with TCB
287                          * Then the service main function will get this.
288                          */
289                         packet_info = malloc(sizeof(*packet_info));
290                         if (!packet_info) {
291                                 ret = -errno;
292                                 ErrPrint("Heap: %s\n", strerror(errno));
293                                 packet_destroy(packet);
294                                 break;
295                         }
296
297                         packet_info->packet = packet;
298                         packet_info->tcb = tcb;
299
300                         CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
301                         svc_ctx->packet_list = eina_list_append(svc_ctx->packet_list, packet_info);
302                         CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
303
304                         if (write(svc_ctx->evt_pipe[PIPE_WRITE], &evt_ch, sizeof(evt_ch)) != sizeof(evt_ch)) {
305                                 ret = -errno;
306                                 ErrPrint("Unable to write a pipe: %s\n", strerror(errno));
307                                 CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
308                                 svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info);
309                                 CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
310
311                                 packet_destroy(packet);
312                                 DbgFree(packet_info);
313                                 ErrPrint("Terminate thread: %p\n", tcb);
314                                 break;
315                         } else {
316                                 DbgPrint("Packet received: %d bytes\n", packet_offset);
317                                 recv_state = RECV_INIT;
318                         }
319
320                         /* Take a breathe */
321                         pthread_yield();
322                 }
323         }
324
325         CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
326         EINA_LIST_FOREACH(svc_ctx->packet_list, l, packet_info) {
327                 if (packet_info->tcb == tcb) {
328                         DbgPrint("Reset ptr of the TCB[%p] in the list of packet info\n", tcb);
329                         packet_info->tcb = NULL;
330                 }
331         }
332         CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
333
334         /*!
335          * \note
336          * Emit a signal to collect this TCB from the SERVER THREAD.
337          */
338         if (write(svc_ctx->tcb_pipe[PIPE_WRITE], &tcb, sizeof(tcb)) != sizeof(tcb)) {
339                 ErrPrint("Unable to write pipe: %s\n", strerror(errno));
340         }
341
342         return (void *)ret;
343 }
344
345 /*!
346  * \note
347  * SERVER THREAD
348  */
349 HAPI int service_register_tcb_callback(struct service_context *svc_ctx, struct tcb *tcb, enum tcb_event_type event, void (*cb)(struct service_context *svc_ctx, struct tcb *tcb, void *data), void *data)
350 {
351         struct tcb_event_cbdata *cbdata;
352
353         cbdata = malloc(sizeof(*cbdata));
354         if (!cbdata) {
355                 ErrPrint("Heap: %s\n", strerror(errno));
356                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
357         }
358
359         cbdata->tcb = tcb;
360         cbdata->cb = cb;
361         cbdata->data = data;
362
363         switch (event) {
364         case TCB_EVENT_CREATE:
365                 if (tcb) {
366                         DbgPrint("To catch the create event of TCB does not requires \"tcb\" handle\n");
367                 }
368                 svc_ctx->tcb_create_cb_list = eina_list_append(svc_ctx->tcb_create_cb_list, cbdata);
369                 break;
370         case TCB_EVENT_DESTROY:
371                 svc_ctx->tcb_destroy_cb_list = eina_list_append(svc_ctx->tcb_destroy_cb_list, cbdata);
372                 break;
373         default:
374                 DbgFree(cbdata);
375                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
376         }
377
378         return DBOX_STATUS_ERROR_NONE;
379 }
380
381 /*!
382  * \note
383  * SERVER THREAD
384  */
385 HAPI int service_unregister_tcb_callback(struct service_context *svc_ctx, struct tcb *tcb, enum tcb_event_type event, void (*cb)(struct service_context *svc_ctx, struct tcb *tcb, void *data), void *data)
386 {
387         struct tcb_event_cbdata *cbdata;
388         Eina_List *l;
389
390         switch (event) {
391         case TCB_EVENT_CREATE:
392                 EINA_LIST_FOREACH(svc_ctx->tcb_create_cb_list, l, cbdata) {
393                         if (cbdata->tcb == tcb && cbdata->cb == cb && cbdata->data == data) {
394                                 svc_ctx->tcb_create_cb_list = eina_list_remove(svc_ctx->tcb_create_cb_list, cbdata);
395                                 DbgFree(cbdata);
396                                 return DBOX_STATUS_ERROR_NONE;
397                         }
398                 }
399                 break;
400         case TCB_EVENT_DESTROY:
401                 EINA_LIST_FOREACH(svc_ctx->tcb_destroy_cb_list, l, cbdata) {
402                         if (cbdata->tcb == tcb && cbdata->cb == cb && cbdata->data == data) {
403                                 svc_ctx->tcb_destroy_cb_list = eina_list_remove(svc_ctx->tcb_destroy_cb_list, cbdata);
404                                 DbgFree(cbdata);
405                                 return DBOX_STATUS_ERROR_NONE;
406                         }
407                 }
408                 break;
409         default:
410                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
411         }
412
413         return DBOX_STATUS_ERROR_NOT_EXIST;
414 }
415
416 /*!
417  * \note
418  * SERVER THREAD
419  */
420 static inline struct tcb *tcb_create(struct service_context *svc_ctx, int fd)
421 {
422         struct tcb *tcb;
423         int status;
424         struct tcb_event_cbdata *cbdata;
425         Eina_List *l;
426         Eina_List *n;
427
428         tcb = malloc(sizeof(*tcb));
429         if (!tcb) {
430                 ErrPrint("Heap: %s\n", strerror(errno));
431                 return NULL;
432         }
433
434         if (pipe2(tcb->ctrl_pipe, O_CLOEXEC) < 0) {
435                 ErrPrint("pipe2: %s\n", strerror(errno));
436                 DbgFree(tcb);
437                 return NULL;
438         }
439
440         tcb->fd = fd;
441         tcb->svc_ctx = svc_ctx;
442         tcb->type = TCB_CLIENT_TYPE_APP;
443         tcb->pid = -1;
444
445         DbgPrint("Create a new service thread [%d]\n", fd);
446         status = pthread_create(&tcb->thid, NULL, client_packet_pump_main, tcb);
447         if (status != 0) {
448                 ErrPrint("Unable to create a new thread: %s\n", strerror(status));
449                 CLOSE_PIPE(tcb->ctrl_pipe);
450                 DbgFree(tcb);
451                 return NULL;
452         }
453
454         CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock);
455         svc_ctx->tcb_list = eina_list_append(svc_ctx->tcb_list, tcb);
456         CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock);
457
458         EINA_LIST_FOREACH_SAFE(svc_ctx->tcb_create_cb_list, l, n, cbdata) {
459                 if (!cbdata->cb) {
460                         /* ASSERT */
461                         ErrPrint("invalid CB\n");
462                         svc_ctx->tcb_create_cb_list = eina_list_remove(svc_ctx->tcb_create_cb_list, cbdata);
463                         DbgFree(cbdata);
464                         continue;
465                 }
466
467                 cbdata->cb(svc_ctx, tcb, cbdata->data);
468         }
469
470         return tcb;
471 }
472
473 /*!
474  * \note
475  * SERVER THREAD
476  */
477 static inline void tcb_teminate_all(struct service_context *svc_ctx)
478 {
479         struct tcb *tcb;
480         void *ret;
481         int status;
482         char ch = EVT_END_CH;
483
484         /*!
485          * We don't need to make critical section on here.
486          * If we call this after terminate the server thread first.
487          * Then there is no other thread to access tcb_list.
488          */
489         EINA_LIST_FREE(svc_ctx->tcb_list, tcb) {
490                 /*!
491                  * ASSERT(tcb->fd >= 0);
492                  */
493                 if (write(tcb->ctrl_pipe[PIPE_WRITE], &ch, sizeof(ch)) != sizeof(ch)) {
494                         ErrPrint("write: %s\n", strerror(errno));
495                 }
496
497                 status = pthread_join(tcb->thid, &ret);
498                 if (status != 0) {
499                         ErrPrint("Unable to join a thread: %s\n", strerror(status));
500                 } else {
501                         DbgPrint("Thread returns: %p\n", ret);
502                 }
503
504                 secure_socket_destroy_handle(tcb->fd);
505
506                 CLOSE_PIPE(tcb->ctrl_pipe);
507                 DbgFree(tcb);
508         }
509 }
510
511 /*!
512  * \note
513  * SERVER THREAD
514  */
515 static inline void tcb_destroy(struct service_context *svc_ctx, struct tcb *tcb)
516 {
517         void *ret;
518         int status;
519         char ch = EVT_END_CH;
520         struct tcb_event_cbdata *cbdata;
521         Eina_List *l;
522         Eina_List *n;
523
524         EINA_LIST_FOREACH_SAFE(svc_ctx->tcb_destroy_cb_list, l, n, cbdata) {
525                 if (!cbdata->cb) {
526                         /* ASSERT */
527                         ErrPrint("invalid CB\n");
528                         svc_ctx->tcb_destroy_cb_list = eina_list_remove(svc_ctx->tcb_destroy_cb_list, cbdata);
529                         DbgFree(cbdata);
530                         continue;
531                 }
532
533                 if (cbdata->tcb != tcb) {
534                         continue;
535                 }
536
537                 cbdata->cb(svc_ctx, tcb, cbdata->data);
538
539                 if (eina_list_data_find(svc_ctx->tcb_destroy_cb_list, cbdata)) {
540                         svc_ctx->tcb_destroy_cb_list = eina_list_remove(svc_ctx->tcb_destroy_cb_list, cbdata);
541                         DbgFree(cbdata);
542                 }
543         }
544
545         CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock);
546         svc_ctx->tcb_list = eina_list_remove(svc_ctx->tcb_list, tcb);
547         CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock);
548         /*!
549          * ASSERT(tcb->fd >= 0);
550          * Close the connection, and then collecting the return value of thread
551          */
552         if (write(tcb->ctrl_pipe[PIPE_WRITE], &ch, sizeof(ch)) != sizeof(ch)) {
553                 ErrPrint("write: %s\n", strerror(errno));
554         }
555
556         status = pthread_join(tcb->thid, &ret);
557         if (status != 0) {
558                 ErrPrint("Unable to join a thread: %s\n", strerror(status));
559         } else {
560                 DbgPrint("Thread returns: %p\n", ret);
561         }
562
563         secure_socket_destroy_handle(tcb->fd);
564
565         CLOSE_PIPE(tcb->ctrl_pipe);
566         DbgFree(tcb);
567 }
568
569 /*!
570  * \note
571  * SERVER THREAD
572  */
573 static inline int update_fdset(struct service_context *svc_ctx, fd_set *set)
574 {
575         Eina_List *l;
576         struct service_event_item *item;
577         int fd = 0;
578
579         FD_ZERO(set);
580
581         FD_SET(svc_ctx->fd, set);
582         fd = svc_ctx->fd;
583
584         FD_SET(svc_ctx->tcb_pipe[PIPE_READ], set);
585         if (svc_ctx->tcb_pipe[PIPE_READ] > fd) {
586                 fd = svc_ctx->tcb_pipe[PIPE_READ];
587         }
588
589         FD_SET(svc_ctx->evt_pipe[PIPE_READ], set);
590         if (svc_ctx->evt_pipe[PIPE_READ] > fd) {
591                 fd = svc_ctx->evt_pipe[PIPE_READ];
592         }
593
594         EINA_LIST_FOREACH(svc_ctx->event_list, l, item) {
595                 if (item->type == SERVICE_EVENT_TIMER) {
596                         FD_SET(item->info.timer.fd, set);
597                         if (fd < item->info.timer.fd) {
598                                 fd = item->info.timer.fd;
599                         }
600                 }
601         }
602
603         return fd + 1;
604 }
605
606 /*!
607  * \note
608  * SERVER THREAD
609  */
610 static inline void processing_timer_event(struct service_context *svc_ctx, fd_set *set)
611 {
612         uint64_t expired_count;
613         Eina_List *l;
614         Eina_List *n;
615         struct service_event_item *item;
616
617         EINA_LIST_FOREACH_SAFE(svc_ctx->event_list, l, n, item) {
618                 switch (item->type) {
619                 case SERVICE_EVENT_TIMER:
620                         if (!FD_ISSET(item->info.timer.fd, set)) {
621                                 break;
622                         }
623
624                         if (read(item->info.timer.fd, &expired_count, sizeof(expired_count)) == sizeof(expired_count)) {
625                                 DbgPrint("Expired %d times\n", expired_count);
626                                 if (item->event_cb(svc_ctx, item->cbdata) >= 0) {
627                                         break;
628                                 }
629                         } else {
630                                 ErrPrint("read: %s\n", strerror(errno));
631                         }
632
633                         if (!eina_list_data_find(svc_ctx->event_list, item)) {
634                                 break;
635                         }
636
637                         svc_ctx->event_list = eina_list_remove(svc_ctx->event_list, item);
638                         if (close(item->info.timer.fd) < 0) {
639                                 ErrPrint("close: %s\n", strerror(errno));
640                         }
641                         DbgFree(item);
642                         break;
643                 default:
644                         ErrPrint("Unknown event: %d\n", item->type);
645                         break;
646                 }
647         }
648 }
649
650 /*!
651  * Accept new client connections
652  * And create a new thread for service.
653  *
654  * Create Client threads & Destroying them
655  * SERVER THREAD
656  */
657 static void *server_main(void *data)
658 {
659         struct service_context *svc_ctx = data;
660         fd_set set;
661         fd_set except_set;
662         long ret;
663         int client_fd;
664         struct tcb *tcb;
665         int fd;
666         char evt_ch;
667         struct packet_info *packet_info;
668
669         DbgPrint("Server thread is activated\n");
670         while (1) {
671                 fd = update_fdset(svc_ctx, &set);
672                 memcpy(&except_set, &set, sizeof(set));
673
674                 ret = select(fd, &set, NULL, &except_set, NULL);
675                 if (ret < 0) {
676                         ret = -errno;
677                         if (errno == EINTR) {
678                                 DbgPrint("INTERRUPTED\n");
679                                 continue;
680                         }
681                         ErrPrint("Error: %s\n", strerror(errno));
682                         break;
683                 } else if (ret == 0) {
684                         ErrPrint("Timeout\n");
685                         ret = -ETIMEDOUT;
686                         break;
687                 }
688
689                 if (FD_ISSET(svc_ctx->fd, &set)) {
690                         client_fd = secure_socket_get_connection_handle(svc_ctx->fd);
691                         if (client_fd < 0) {
692                                 ErrPrint("Failed to establish a new connection [%d]\n", svc_ctx->fd);
693                                 ret = -EFAULT;
694                                 break;
695                         }
696
697                         tcb = tcb_create(svc_ctx, client_fd);
698                         if (!tcb) {
699                                 ErrPrint("Failed to create a new TCB: %d (%d)\n", client_fd, svc_ctx->fd);
700                                 secure_socket_destroy_handle(client_fd);
701                         }
702                 }
703
704                 if (FD_ISSET(svc_ctx->evt_pipe[PIPE_READ], &set)) {
705                         if (read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch)) != sizeof(evt_ch)) {
706                                 ErrPrint("Unable to read pipe: %s\n", strerror(errno));
707                                 ret = -EFAULT;
708                                 break;
709                         }
710
711                         CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
712                         packet_info = eina_list_nth(svc_ctx->packet_list, 0);
713                         svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info);
714                         CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
715
716                         if (packet_info) {
717                                 /*!
718                                  * \CRITICAL
719                                  * What happens if the client thread is terminated, so the packet_info->tcb is deleted
720                                  * while processing svc_ctx->service_thread_main?
721                                  */
722                                 ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data);
723                                 if (ret < 0) {
724                                         ErrPrint("Service thread returns: %d\n", ret);
725                                 }
726
727                                 packet_destroy(packet_info->packet);
728                                 DbgFree(packet_info);
729                         }
730
731                         /* Take a breathe */
732                         pthread_yield();
733                 }
734
735                 processing_timer_event(svc_ctx, &set);
736
737                 /*!
738                  * \note
739                  * Destroying TCB should be processed at last.
740                  */
741                 if (FD_ISSET(svc_ctx->tcb_pipe[PIPE_READ], &set)) {
742                         Eina_List *lockfree_packet_list;
743                         Eina_List *l;
744                         Eina_List *n;
745
746                         if (read(svc_ctx->tcb_pipe[PIPE_READ], &tcb, sizeof(tcb)) != sizeof(tcb)) {
747                                 ErrPrint("Unable to read pipe: %s\n", strerror(errno));
748                                 ret = -EFAULT;
749                                 break;
750                         }
751
752                         if (!tcb) {
753                                 ErrPrint("Terminate service thread\n");
754                                 ret = -ECANCELED;
755                                 break;
756                         }
757
758                         lockfree_packet_list = NULL;
759                         CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
760                         EINA_LIST_FOREACH_SAFE(svc_ctx->packet_list, l, n, packet_info) {
761                                 if (packet_info->tcb != tcb) {
762                                         continue;
763                                 }
764
765                                 svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info);
766                                 lockfree_packet_list = eina_list_append(lockfree_packet_list, packet_info);
767                         }
768                         CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
769
770                         EINA_LIST_FREE(lockfree_packet_list, packet_info) {
771                                 ret = read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch));
772                                 DbgPrint("Flushing filtered pipe: %d (%c)\n", ret, evt_ch);
773                                 ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data);
774                                 if (ret < 0) {
775                                         ErrPrint("Service thread returns: %d\n", ret);
776                                 }
777                                 packet_destroy(packet_info->packet);
778                                 DbgFree(packet_info);
779                         }
780
781                         /*!
782                          * \note
783                          * Invoke the service thread main, to notify the termination of a TCB
784                          */
785                         ret = svc_ctx->service_thread_main(tcb, NULL, svc_ctx->service_thread_data);
786
787                         /*!
788                          * at this time, the client thread can access this tcb.
789                          * how can I protect this TCB from deletion without disturbing the server thread?
790                          */
791                         tcb_destroy(svc_ctx, tcb);
792                 }
793
794                 /* If there is no such triggered FD? */
795         }
796
797         /*!
798          * Consuming all pended packets before terminates server thread.
799          *
800          * If the server thread is terminated, we should flush all pended packets.
801          * And we should services them.
802          * While processing this routine, the mutex is locked.
803          * So every other client thread will be slowed down, sequently, every clients can meet problems.
804          * But in case of termination of server thread, there could be systemetic problem.
805          * This only should be happenes while terminating the master daemon process.
806          */
807         CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
808         EINA_LIST_FREE(svc_ctx->packet_list, packet_info) {
809                 ret = read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch));
810                 DbgPrint("Flushing pipe: %d (%c)\n", ret, evt_ch);
811                 ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data);
812                 if (ret < 0) {
813                         ErrPrint("Service thread returns: %d\n", ret);
814                 }
815                 packet_destroy(packet_info->packet);
816                 DbgFree(packet_info);
817         }
818         CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
819
820         tcb_teminate_all(svc_ctx);
821         return (void *)ret;
822 }
823
824 /*!
825  * \NOTE
826  * MAIN THREAD
827  */
828 HAPI struct service_context *service_common_create(const char *addr, int (*service_thread_main)(struct tcb *tcb, struct packet *packet, void *data), void *data)
829 {
830         int status;
831         struct service_context *svc_ctx;
832
833         if (!service_thread_main || !addr) {
834                 ErrPrint("Invalid argument\n");
835                 return NULL;
836         }
837
838         if (strncmp(addr, COM_CORE_REMOTE_SCHEME, strlen(COM_CORE_REMOTE_SCHEME))) {
839                 int offset = 0;
840
841                 offset = strlen(COM_CORE_LOCAL_SCHEME);
842                 if (strncmp(addr, COM_CORE_LOCAL_SCHEME, offset)) {
843                         offset = 0;
844                 }
845
846                 if (unlink(addr + offset) < 0) {
847                         ErrPrint("[%s] - %s\n", addr, strerror(errno));
848                 }
849         }
850
851         svc_ctx = calloc(1, sizeof(*svc_ctx));
852         if (!svc_ctx) {
853                 ErrPrint("Heap: %s\n", strerror(errno));
854                 return NULL;
855         }
856
857         svc_ctx->fd = secure_socket_create_server(addr);
858         if (svc_ctx->fd < 0) {
859                 DbgFree(svc_ctx);
860                 return NULL;
861         }
862
863         svc_ctx->service_thread_main = service_thread_main;
864         svc_ctx->service_thread_data = data;
865
866         if (fcntl(svc_ctx->fd, F_SETFD, FD_CLOEXEC) < 0) {
867                 ErrPrint("fcntl: %s\n", strerror(errno));
868         }
869
870         if (fcntl(svc_ctx->fd, F_SETFL, O_NONBLOCK) < 0) {
871                 ErrPrint("fcntl: %s\n", strerror(errno));
872         }
873
874         if (pipe2(svc_ctx->evt_pipe, O_CLOEXEC) < 0) {
875                 ErrPrint("pipe: %d\n", strerror(errno));
876                 secure_socket_destroy_handle(svc_ctx->fd);
877                 DbgFree(svc_ctx);
878                 return NULL;
879         }
880
881         if (pipe2(svc_ctx->tcb_pipe, O_CLOEXEC) < 0) {
882                 ErrPrint("pipe: %s\n", strerror(errno));
883                 CLOSE_PIPE(svc_ctx->evt_pipe);
884                 secure_socket_destroy_handle(svc_ctx->fd);
885                 DbgFree(svc_ctx);
886                 return NULL;
887         }
888
889         status = pthread_mutex_init(&svc_ctx->packet_list_lock, NULL);
890         if (status != 0) {
891                 ErrPrint("Unable to create a mutex: %s\n", strerror(status));
892                 CLOSE_PIPE(svc_ctx->evt_pipe);
893                 CLOSE_PIPE(svc_ctx->tcb_pipe);
894                 secure_socket_destroy_handle(svc_ctx->fd);
895                 DbgFree(svc_ctx);
896                 return NULL;
897         }
898
899         DbgPrint("Creating server thread\n");
900         status = pthread_create(&svc_ctx->server_thid, NULL, server_main, svc_ctx);
901         if (status != 0) {
902                 ErrPrint("Unable to create a thread for shortcut service: %s\n", strerror(status));
903                 status = pthread_mutex_destroy(&svc_ctx->packet_list_lock);
904                 if (status != 0) {
905                         ErrPrint("Error: %s\n", strerror(status));
906                 }
907                 CLOSE_PIPE(svc_ctx->evt_pipe);
908                 CLOSE_PIPE(svc_ctx->tcb_pipe);
909                 secure_socket_destroy_handle(svc_ctx->fd);
910                 DbgFree(svc_ctx);
911                 return NULL;
912         }
913
914         /*!
915          * \note
916          * To give a chance to run for server thread.
917          */
918         pthread_yield();
919
920         return svc_ctx;
921 }
922
923 /*!
924  * \note
925  * MAIN THREAD
926  */
927 HAPI int service_common_destroy(struct service_context *svc_ctx)
928 {
929         int status = 0;
930         void *ret;
931
932         if (!svc_ctx) {
933                 return -EINVAL;
934         }
935
936         /*!
937          * \note
938          * Terminate server thread
939          */
940         if (write(svc_ctx->tcb_pipe[PIPE_WRITE], &status, sizeof(status)) != sizeof(status)) {
941                 ErrPrint("Failed to write: %s\n", strerror(errno));
942         }
943
944         status = pthread_join(svc_ctx->server_thid, &ret);
945         if (status != 0) {
946                 ErrPrint("Join: %s\n", strerror(status));
947         } else {
948                 DbgPrint("Thread returns: %p\n", ret);
949         }
950
951         secure_socket_destroy_handle(svc_ctx->fd);
952
953         status = pthread_mutex_destroy(&svc_ctx->packet_list_lock);
954         if (status != 0) {
955                 ErrPrint("Unable to destroy a mutex: %s\n", strerror(status));
956         }
957
958         CLOSE_PIPE(svc_ctx->evt_pipe);
959         CLOSE_PIPE(svc_ctx->tcb_pipe);
960         DbgFree(svc_ctx);
961         return 0;
962 }
963
964 /*!
965  * \note
966  * SERVER THREAD or OTHER THREAD (not main)
967  */
968 HAPI int tcb_is_valid(struct service_context *svc_ctx, struct tcb *tcb)
969 {
970         Eina_List *l;
971         struct tcb *tmp;
972         int ret = -ENOENT;
973
974         CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock);
975         EINA_LIST_FOREACH(svc_ctx->tcb_list, l, tmp) {
976                 if (tmp == tcb /* && tcb->svc_ctx == svc_ctx */) {
977                         ret = tcb->fd;
978                         break;
979                 }
980         }
981         CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock);
982
983         return ret;
984 }
985
986 /*!
987  * \note
988  * SERVER THREAD
989  */
990 HAPI int tcb_pid(struct tcb *tcb)
991 {
992         if (!tcb) {
993                 return -1;
994         }
995
996         return tcb->pid;
997 }
998
999 /*!
1000  * \note
1001  * SERVER THREAD
1002  */
1003 HAPI int tcb_fd(struct tcb *tcb)
1004 {
1005         if (!tcb) {
1006                 return -EINVAL;
1007         }
1008
1009         return tcb->fd;
1010 }
1011
1012 /*!
1013  * \note
1014  * SERVER THREAD
1015  */
1016 HAPI int tcb_client_type(struct tcb *tcb)
1017 {
1018         if (!tcb) {
1019                 return -EINVAL;
1020         }
1021
1022         return tcb->type;
1023 }
1024
1025 /*!
1026  * \note
1027  * SERVER THREAD
1028  */
1029 HAPI int tcb_client_type_set(struct tcb *tcb, enum tcb_type type)
1030 {
1031         if (!tcb) {
1032                 return -EINVAL;
1033         }
1034
1035         DbgPrint("TCB[%p] Client type is changed to %d from %d\n", tcb, type, tcb->type);
1036         tcb->type = type;
1037         return 0;
1038 }
1039
1040 /*!
1041  * \note
1042  * SERVER THREAD
1043  */
1044 HAPI struct service_context *tcb_svc_ctx(struct tcb *tcb)
1045 {
1046         if (!tcb) {
1047                 return NULL;
1048         }
1049
1050         return tcb->svc_ctx;
1051 }
1052
1053 /*!
1054  * \note
1055  * SERVER THREAD
1056  */
1057 HAPI int service_common_unicast_packet(struct tcb *tcb, struct packet *packet)
1058 {
1059         if (!tcb || !packet) {
1060                 DbgPrint("Invalid unicast: tcb[%p], packet[%p]\n", tcb, packet);
1061                 return -EINVAL;
1062         }
1063
1064         DbgPrint("Unicast packet\n");
1065         return com_core_send(tcb->fd, (void *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
1066 }
1067
1068 /*!
1069  * \note
1070  * SERVER THREAD
1071  */
1072 HAPI int service_common_multicast_packet(struct tcb *tcb, struct packet *packet, int type)
1073 {
1074         Eina_List *l;
1075         struct tcb *target;
1076         struct service_context *svc_ctx;
1077         int ret;
1078
1079         if (!tcb || !packet) {
1080                 DbgPrint("Invalid multicast: tcb[%p], packet[%p]\n", tcb, packet);
1081                 return -EINVAL;
1082         }
1083
1084         svc_ctx = tcb->svc_ctx;
1085
1086         DbgPrint("Multicasting packets\n");
1087
1088         /*!
1089          * \note
1090          * Does not need to make a critical section from here.
1091          */
1092         EINA_LIST_FOREACH(svc_ctx->tcb_list, l, target) {
1093                 if (target == tcb || target->type != type) {
1094                         DbgPrint("Skip target: %p(%d) == %p/%d\n", target, target->type, tcb, type);
1095                         continue;
1096                 }
1097
1098                 ret = com_core_send(target->fd, (void *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
1099                 if (ret < 0) {
1100                         ErrPrint("Failed to send packet: %d\n", ret);
1101                 }
1102         }
1103         DbgPrint("Finish to multicast packet\n");
1104         return 0;
1105 }
1106
1107 /*!
1108  * \note
1109  * SERVER THREAD
1110  */
1111 HAPI struct service_event_item *service_common_add_timer(struct service_context *svc_ctx, double timer, int (*timer_cb)(struct service_context *svc_cx, void *data), void *data)
1112 {
1113         struct service_event_item *item;
1114
1115         item = calloc(1, sizeof(*item));
1116         if (!item) {
1117                 ErrPrint("Heap: %s\n", strerror(errno));
1118                 return NULL;
1119         }
1120
1121         item->type = SERVICE_EVENT_TIMER;
1122         item->info.timer.fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
1123         if (item->info.timer.fd < 0) {
1124                 ErrPrint("Error: %s\n", strerror(errno));
1125                 DbgFree(item);
1126                 return NULL;
1127         }
1128
1129         if (service_common_update_timer(item, timer) < 0) {
1130                 if (close(item->info.timer.fd) < 0) {
1131                         ErrPrint("close: %s\n", strerror(errno));
1132                 }
1133                 DbgFree(item);
1134                 return NULL;
1135         }
1136
1137         item->event_cb = timer_cb;
1138         item->cbdata = data;
1139
1140         svc_ctx->event_list = eina_list_append(svc_ctx->event_list, item);
1141         return item;
1142 }
1143
1144 HAPI int service_common_update_timer(struct service_event_item *item, double timer)
1145 {
1146         struct itimerspec spec;
1147
1148         spec.it_interval.tv_sec = (time_t)timer;
1149         spec.it_interval.tv_nsec = (timer - spec.it_interval.tv_sec) * 1000000000;
1150
1151         if (clock_gettime(CLOCK_MONOTONIC, &spec.it_value) < 0) {
1152                 ErrPrint("clock_gettime: %s\n", strerror(errno));
1153                 return -EFAULT;
1154         }
1155
1156         spec.it_value.tv_sec += spec.it_interval.tv_sec;
1157         spec.it_value.tv_nsec += spec.it_interval.tv_nsec;
1158
1159         if (timerfd_settime(item->info.timer.fd, TFD_TIMER_ABSTIME, &spec, NULL) < 0) {
1160                 ErrPrint("Error: %s\n", strerror(errno));
1161                 return -EFAULT;
1162         }
1163
1164         DbgPrint("Armed interval: %u %u\n", spec.it_interval.tv_sec, spec.it_interval.tv_nsec);
1165         return 0;
1166 }
1167
1168 /*!
1169  * \note
1170  * SERVER THREAD
1171  */
1172 HAPI int service_common_del_timer(struct service_context *svc_ctx, struct service_event_item *item)
1173 {
1174         if (!eina_list_data_find(svc_ctx->event_list, item)) {
1175                 ErrPrint("Invalid event item\n");
1176                 return -EINVAL;
1177         }
1178
1179         svc_ctx->event_list = eina_list_remove(svc_ctx->event_list, item);
1180
1181         if (close(item->info.timer.fd) < 0) {
1182                 ErrPrint("close: %s\n", strerror(errno));
1183         }
1184         DbgFree(item);
1185         return 0;
1186 }
1187
1188 HAPI int service_common_fd(struct service_context *ctx)
1189 {
1190         return ctx->fd;
1191 }
1192
1193 /* End of a file */