2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
23 #include <livebox-errno.h>
26 #include <sys/smack.h>
28 #include "critical_log.h"
29 #include "service_common.h"
30 #include "utility_service.h"
36 #define SVC_PKG "com.samsung.data-provider-slave.icon"
39 #ifndef LAUNCH_TIMEOUT
40 #define LAUNCH_TIMEOUT 10.0f
44 Eina_List *pending_list;
45 Eina_List *context_list;
46 struct service_context *svc_ctx;
48 struct tcb *svc_daemon;
49 int svc_daemon_is_launched;
51 struct service_event_item *launch_timer;
52 struct service_event_item *delay_launcher;
55 .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
56 .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
59 .svc_daemon_is_launched = 0,
62 .delay_launcher = NULL,
67 struct packet *packet;
75 static int lazy_launcher_cb(struct service_context *svc_ctx, void *data);
77 static int put_reply_tcb(struct tcb *tcb, double seq)
81 ctx = malloc(sizeof(*ctx));
83 ErrPrint("Heap: %s\n", strerror(errno));
84 return LB_STATUS_ERROR_MEMORY;
90 s_info.context_list = eina_list_append(s_info.context_list, ctx);
91 return LB_STATUS_SUCCESS;
94 static inline struct tcb *get_reply_tcb(double seq)
101 EINA_LIST_FOREACH_SAFE(s_info.context_list, l, n, ctx) {
102 if (ctx->seq != seq) {
106 s_info.context_list = eina_list_remove(s_info.context_list, ctx);
115 static inline int flush_pended_request(void)
118 * Flush all pended requests
120 struct pending_item *item;
123 EINA_LIST_FREE(s_info.pending_list, item) {
124 ret = service_common_unicast_packet(s_info.svc_daemon, item->packet);
126 struct packet *reply;
127 reply = packet_create_reply(item->packet, "i", ret);
128 if (service_common_unicast_packet(item->tcb, reply) < 0) {
129 ErrPrint("Unable to send packet\n");
131 packet_destroy(reply);
133 put_reply_tcb(item->tcb, packet_seq(item->packet));
135 packet_unref(item->packet);
142 static inline int put_pended_request(struct tcb *tcb, struct packet *packet)
144 struct pending_item *item;
146 item = malloc(sizeof(*item));
148 ErrPrint("Heap: %s\n", strerror(errno));
149 return LB_STATUS_ERROR_MEMORY;
153 item->packet = packet_ref(packet);
156 ErrPrint("Unable to ref packet\n");
157 return LB_STATUS_ERROR_FAULT;
160 s_info.pending_list = eina_list_append(s_info.pending_list, item);
164 static int launch_timeout_cb(struct service_context *svc_ctx, void *data)
166 struct pending_item *item;
167 struct packet *reply;
169 EINA_LIST_FREE(s_info.pending_list, item) {
170 reply = packet_create_reply(item->packet, "i", -EFAULT);
172 ErrPrint("Unable to create a packet\n");
176 ret = service_common_unicast_packet(item->tcb, reply);
178 ErrPrint("Failed to send reply packet: %d\n", ret);
181 packet_destroy(reply);
184 packet_unref(item->packet);
188 s_info.launch_timer = NULL;
189 s_info.svc_daemon_is_launched = 0;
190 return -ECANCELED; /* Delete this timer */
193 static inline int launch_svc(struct service_context *svc_ctx)
196 int ret = LB_STATUS_SUCCESS;
198 pid = aul_launch_app(SVC_PKG, NULL);
200 //case AUL_R_EHIDDENFORGUEST: /**< App hidden for guest mode */
201 case AUL_R_ENOLAUNCHPAD: /**< no launchpad */
202 case AUL_R_EILLACC: /**< Illegal Access */
203 case AUL_R_EINVAL: /**< Invalid argument */
204 case AUL_R_ENOINIT: /**< AUL handler NOT initialized */
205 case AUL_R_ERROR: /**< General error */
206 ErrPrint("Failed to launch an app: %s(%d)\n", SVC_PKG, pid);
207 ret = LB_STATUS_ERROR_FAULT;
209 case AUL_R_ETIMEOUT: /**< Timeout */
210 case AUL_R_ECOMM: /**< Comunication Error */
211 case AUL_R_ETERMINATING: /**< application terminating */
212 case AUL_R_ECANCELED: /**< Operation canceled */
213 /* Need time to launch app again */
214 ErrPrint("Terminating now, try to launch this after few sec later: %s(%d)\n", SVC_PKG, pid);
215 s_info.svc_daemon_is_launched = 1;
216 s_info.delay_launcher = service_common_add_timer(svc_ctx, LAUNCH_TIMEOUT, lazy_launcher_cb, NULL);
217 if (!s_info.delay_launcher) {
218 ErrPrint("Unable to add delay launcher\n");
219 ret = LB_STATUS_ERROR_FAULT;
222 case AUL_R_LOCAL: /**< Launch by himself */
223 case AUL_R_OK: /**< General success */
225 DbgPrint("Launched: %s(%d)\n", SVC_PKG, pid);
226 s_info.svc_daemon_is_launched = 1;
227 s_info.launch_timer = service_common_add_timer(svc_ctx, LAUNCH_TIMEOUT, launch_timeout_cb, NULL);
228 if (!s_info.launch_timer) {
229 ErrPrint("Unable to create launch timer\n");
236 static int lazy_launcher_cb(struct service_context *svc_ctx, void *data)
238 s_info.svc_daemon_is_launched = launch_svc(svc_ctx) == LB_STATUS_SUCCESS;
239 s_info.delay_launcher = NULL;
243 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
245 struct packet *reply;
250 DbgPrint("TCB %p is terminated (NIL packet)\n", tcb);
252 if (tcb == s_info.svc_daemon) {
253 s_info.svc_daemon = NULL;
254 s_info.svc_daemon_is_launched = 0;
257 return LB_STATUS_SUCCESS;
260 cmd = packet_command(packet);
262 ErrPrint("Invalid packet\n");
263 return LB_STATUS_ERROR_INVALID;
266 switch (packet_type(packet)) {
268 if (!s_info.svc_daemon_is_launched) {
269 ret = launch_svc(tcb_svc_ctx(tcb));
270 if (ret != LB_STATUS_SUCCESS) {
275 if (!s_info.svc_daemon) {
276 ret = put_pended_request(tcb, packet);
281 ret = service_common_unicast_packet(s_info.svc_daemon, packet);
286 put_reply_tcb(tcb, packet_seq(packet));
290 case PACKET_REQ_NOACK:
291 if (!strcmp(cmd, "service_register")) {
292 if (!s_info.svc_daemon_is_launched) {
293 ErrPrint("Service daemon is not launched. but something tries to register a service\n");
294 return LB_STATUS_ERROR_INVALID;
297 if (s_info.svc_daemon) {
298 ErrPrint("Service daemon is already prepared\n");
299 return LB_STATUS_ERROR_INVALID;
302 if (s_info.launch_timer) {
303 service_common_del_timer(tcb_svc_ctx(tcb), s_info.launch_timer);
304 s_info.launch_timer = NULL;
307 s_info.svc_daemon = tcb;
308 flush_pended_request();
312 tcb = get_reply_tcb(packet_seq(packet));
314 ErrPrint("Unable to find reply tcb\n");
316 ret = service_common_unicast_packet(tcb, packet);
318 ErrPrint("Unable to forward the reply packet\n");
323 ErrPrint("Packet type is not valid[%s]\n", cmd);
324 return LB_STATUS_ERROR_INVALID;
327 return LB_STATUS_SUCCESS;
330 ErrPrint("Error: %d\n", ret);
331 reply = packet_create_reply(packet, "i", ret);
332 if (service_common_unicast_packet(tcb, reply) < 0) {
333 ErrPrint("Unable to send reply packet\n");
335 packet_destroy(reply);
339 int utility_service_init(void)
341 if (s_info.svc_ctx) {
342 ErrPrint("Already initialized\n");
343 return LB_STATUS_ERROR_ALREADY;
346 s_info.svc_ctx = service_common_create(UTILITY_SOCKET, service_thread_main, NULL);
347 if (!s_info.svc_ctx) {
348 ErrPrint("Unable to activate service thread\n");
349 return LB_STATUS_ERROR_FAULT;
352 if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), UTILITY_SMACK_LABEL, SMACK_LABEL_IPOUT) != 0) {
353 if (errno != EOPNOTSUPP) {
354 ErrPrint("Unable to set SMACK label(%d)\n", errno);
355 service_common_destroy(s_info.svc_ctx);
356 s_info.svc_ctx = NULL;
357 return LB_STATUS_ERROR_FAULT;
361 if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), UTILITY_SMACK_LABEL, SMACK_LABEL_IPIN) != 0) {
362 if (errno != EOPNOTSUPP) {
363 ErrPrint("Unable to set SMACK label(%d)\n", errno);
364 service_common_destroy(s_info.svc_ctx);
365 s_info.svc_ctx = NULL;
366 return LB_STATUS_ERROR_FAULT;
370 DbgPrint("Successfully initiated\n");
371 return LB_STATUS_SUCCESS;
374 int utility_service_fini(void)
376 if (!s_info.svc_ctx) {
377 return LB_STATUS_ERROR_INVALID;
380 service_common_destroy(s_info.svc_ctx);
381 s_info.svc_ctx = NULL;
382 DbgPrint("Successfully Finalized\n");
383 return LB_STATUS_SUCCESS;