Update SMACK, Fix a crash of terminating sequence, etc, ...
[apps/livebox/data-provider-master.git] / src / shortcut_service.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 #include <stdio.h>
17
18 #include <Eina.h>
19
20 #include <dlog.h>
21 #include <livebox-errno.h>
22 #include <packet.h>
23
24 #include <Eina.h>
25 #include <sys/smack.h>
26
27 #include <security-server.h>
28
29 #include "service_common.h"
30 #include "debug.h"
31 #include "util.h"
32 #include "conf.h"
33
34 static struct info {
35         Eina_List *context_list;
36         struct service_context *svc_ctx;
37 } s_info = {
38         .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
39         .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
40 };
41
42 struct context {
43         struct tcb *tcb;
44         double seq;
45 };
46
47 /*!
48  * SERVICE THREAD
49  */
50 static inline int put_reply_context(struct tcb *tcb, double seq)
51 {
52         struct context *ctx;
53
54         ctx = malloc(sizeof(*ctx));
55         if (!ctx) {
56                 ErrPrint("Heap: %s\n", strerror(errno));
57                 return -ENOMEM;
58         }
59
60         ctx->tcb = tcb;
61         ctx->seq = seq; /* Could we this sequence value is uniq? */
62
63         s_info.context_list = eina_list_append(s_info.context_list, ctx);
64         return 0;
65 }
66
67 /*!
68  * SERVICE THREAD
69  */
70 static inline struct tcb *get_reply_context(double seq)
71 {
72         Eina_List *l;
73         Eina_List *n;
74         struct context *ctx;
75         struct tcb *tcb;
76
77         tcb = NULL;
78         EINA_LIST_FOREACH_SAFE(s_info.context_list, l, n, ctx) {
79                 if (ctx->seq != seq)
80                         continue;
81
82                 s_info.context_list = eina_list_remove(s_info.context_list, ctx);
83                 tcb = ctx->tcb;
84                 free(ctx);
85                 break;
86         }
87
88         return tcb;
89 }
90
91 /*!
92  * SERVICE THREAD
93  */
94 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
95 {
96         const char *command;
97
98         if (!packet) {
99                 DbgPrint("TCB: %p is terminated (NIL packet)\n", tcb);
100                 return 0;
101         }
102
103         command = packet_command(packet);
104         if (!command) {
105                 ErrPrint("Invalid command\n");
106                 return -EINVAL;
107         }
108
109         switch (packet_type(packet)) {
110         case PACKET_REQ:
111                 /* Need to send reply packet */
112                 DbgPrint("%p REQ: Command: [%s]\n", tcb, command);
113                 if (service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE) < 0)
114                         ErrPrint("Unable to send service request packet\n");
115                 else
116                         (void)put_reply_context(tcb, packet_seq(packet));
117                 break;
118         case PACKET_REQ_NOACK:
119                 /* Doesn't need to send reply packet */
120                 DbgPrint("%p REQ_NOACK: Command: [%s]\n", tcb, command);
121                 if (!strcmp(command, "service_register")) {
122                         tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
123                         break;
124                 }
125
126                 if (service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE) < 0)
127                         ErrPrint("Unable to send service reuqest packet\n");
128                 break;
129         case PACKET_ACK:
130                 /* Okay, client(or app) send a reply packet to us. */
131                 DbgPrint("%p ACK: Command: [%s]\n", tcb, command);
132                 tcb = get_reply_context(packet_seq(packet));
133                 if (!tcb) {
134                         ErrPrint("There is no proper context\n");
135                         break;
136                 }
137
138                 if (service_common_unicast_packet(tcb, packet) < 0)
139                         ErrPrint("Unable to send reply packet\n");
140                 break;
141         default:
142                 ErrPrint("Packet type is not valid[%s]\n", command);
143                 return -EINVAL;
144         }
145
146         /*!
147          * return value has no meanning,
148          * it will be printed by dlogutil.
149          */
150         return 0;
151 }
152
153
154 /*!
155  * MAIN THREAD
156  * Do not try to do anyother operation in these functions
157  */
158
159 HAPI int shortcut_service_init(void)
160 {
161         if (s_info.svc_ctx) {
162                 ErrPrint("Already initialized\n");
163                 return LB_STATUS_ERROR_ALREADY;
164         }
165
166         s_info.svc_ctx = service_common_create(SHORTCUT_SOCKET, service_thread_main, NULL);
167         if (!s_info.svc_ctx) {
168                 ErrPrint("Unable to activate service thread\n");
169                 return LB_STATUS_ERROR_FAULT;
170         }
171
172         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), SHORTCUT_SMACK_LABEL, SMACK_LABEL_IPOUT) != 0) {
173                 if (errno != EOPNOTSUPP) {
174                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
175                         service_common_destroy(s_info.svc_ctx);
176                         s_info.svc_ctx = NULL;
177                         return LB_STATUS_ERROR_FAULT;
178                 }
179         }
180
181         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), SHORTCUT_SMACK_LABEL, SMACK_LABEL_IPIN) != 0) {
182                 if (errno != EOPNOTSUPP) {
183                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
184                         service_common_destroy(s_info.svc_ctx);
185                         s_info.svc_ctx = NULL;
186                         return LB_STATUS_ERROR_FAULT;
187                 }
188         }
189
190         DbgPrint("Successfully initiated\n");
191         return LB_STATUS_SUCCESS;
192 }
193
194 HAPI int shortcut_service_fini(void)
195 {
196         if (!s_info.svc_ctx)
197                 return LB_STATUS_ERROR_INVALID;
198
199         service_common_destroy(s_info.svc_ctx);
200         s_info.svc_ctx = NULL;
201         DbgPrint("Successfully Finalized\n");
202         return LB_STATUS_SUCCESS;
203 }
204
205 /* End of a file */