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 "service_common.h"
27 #include "utility_service.h"
32 #define UTILITY_ADDR "/tmp/.utility.service"
33 #define SVC_PKG "org.tizen.data-provider-slave.icon"
34 #define LAUNCH_TIMEOUT 10.0f
37 Eina_List *pending_list;
38 Eina_List *context_list;
39 struct service_context *svc_ctx;
41 struct tcb *svc_daemon;
44 struct service_event_item *launch_timer;
47 .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
48 .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
58 struct packet *packet;
66 static inline int put_reply_tcb(struct tcb *tcb, double seq)
70 ctx = malloc(sizeof(*ctx));
72 ErrPrint("Heap: %s\n", strerror(errno));
73 return LB_STATUS_ERROR_MEMORY;
79 s_info.context_list = eina_list_append(s_info.context_list, ctx);
80 return LB_STATUS_SUCCESS;
83 static inline struct tcb *get_reply_tcb(double seq)
90 EINA_LIST_FOREACH_SAFE(s_info.context_list, l, n, ctx) {
94 s_info.context_list = eina_list_remove(s_info.context_list, ctx);
103 static inline int flush_pended_request(void)
106 * Flush all pended requests
108 struct pending_item *item;
111 EINA_LIST_FREE(s_info.pending_list, item) {
112 ret = service_common_unicast_packet(s_info.svc_daemon, item->packet);
114 struct packet *reply;
115 reply = packet_create_reply(item->packet, "i", ret);
116 if (service_common_unicast_packet(item->tcb, reply) < 0)
117 ErrPrint("Unable to send packet\n");
118 packet_destroy(reply);
120 put_reply_tcb(item->tcb, packet_seq(item->packet));
122 packet_unref(item->packet);
129 static inline int put_pended_request(struct tcb *tcb, struct packet *packet)
131 struct pending_item *item;
133 item = malloc(sizeof(*item));
135 ErrPrint("Heap: %s\n", strerror(errno));
136 return LB_STATUS_ERROR_MEMORY;
140 item->packet = packet_ref(packet);
143 ErrPrint("Unable to ref packet\n");
144 return LB_STATUS_ERROR_FAULT;
147 s_info.pending_list = eina_list_append(s_info.pending_list, item);
151 static int launch_timeout_cb(struct service_context *svc_ctx, void *data)
153 struct pending_item *item;
154 struct packet *reply;
156 EINA_LIST_FREE(s_info.pending_list, item) {
157 reply = packet_create_reply(item->packet, "i", -EFAULT);
159 ErrPrint("Unable to create a packet\n");
163 ret = service_common_unicast_packet(item->tcb, reply);
165 ErrPrint("Failed to send reply packet: %d\n", ret);
167 packet_destroy(reply);
170 packet_unref(item->packet);
174 s_info.launch_timer = NULL;
175 return -ECANCELED; /* Delete this timer */
178 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
180 struct packet *reply;
185 DbgPrint("TCB %p is terminated (NIL packet)\n", tcb);
187 if (tcb == s_info.svc_daemon) {
188 s_info.svc_daemon = NULL;
195 cmd = packet_command(packet);
197 ErrPrint("Invalid packet\n");
198 return LB_STATUS_ERROR_INVALID;
201 switch (packet_type(packet)) {
203 if (s_info.svc_pid < 0) {
204 s_info.svc_pid = aul_launch_app(SVC_PKG, NULL);
205 if (s_info.svc_pid > 0) {
206 s_info.launch_timer = service_common_add_timer(tcb_svc_ctx(tcb), LAUNCH_TIMEOUT, launch_timeout_cb, NULL);
207 if (!s_info.launch_timer)
208 ErrPrint("Unable to create launch timer\n");
212 if (s_info.svc_pid < 0) {
213 ErrPrint("Failed to launch an app: %s(%d)\n", SVC_PKG, s_info.svc_pid);
214 ret = LB_STATUS_ERROR_FAULT;
216 } else if (!s_info.svc_daemon) {
217 ret = put_pended_request(tcb, packet);
221 ret = service_common_unicast_packet(s_info.svc_daemon, packet);
225 put_reply_tcb(tcb, packet_seq(packet));
229 case PACKET_REQ_NOACK:
230 if (!strcmp(cmd, "service_register")) {
231 if (s_info.svc_daemon) {
232 ErrPrint("Service daemon is already prepared\n");
233 return LB_STATUS_ERROR_INVALID;
236 if (s_info.launch_timer) {
237 service_common_del_timer(tcb_svc_ctx(tcb), s_info.launch_timer);
238 s_info.launch_timer = NULL;
241 s_info.svc_daemon = tcb;
242 flush_pended_request();
246 tcb = get_reply_tcb(packet_seq(packet));
248 ErrPrint("Unable to find reply tcb\n");
250 ret = service_common_unicast_packet(tcb, packet);
252 ErrPrint("Unable to forward the reply packet\n");
256 ErrPrint("Packet type is not valid[%s]\n", cmd);
257 return LB_STATUS_ERROR_INVALID;
260 return LB_STATUS_SUCCESS;
263 ErrPrint("Error: %d\n", ret);
264 reply = packet_create_reply(packet, "i", ret);
265 if (service_common_unicast_packet(tcb, reply) < 0)
266 ErrPrint("Unable to send reply packet\n");
267 packet_destroy(reply);
271 int utility_service_init(void)
273 if (s_info.svc_ctx) {
274 ErrPrint("Already initialized\n");
275 return LB_STATUS_ERROR_ALREADY;
278 s_info.svc_ctx = service_common_create(UTILITY_ADDR, service_thread_main, NULL);
279 if (!s_info.svc_ctx) {
280 ErrPrint("Unable to activate service thread\n");
281 return LB_STATUS_ERROR_FAULT;
284 DbgPrint("Successfully initiated\n");
285 return LB_STATUS_SUCCESS;
288 int utility_service_fini(void)
291 return LB_STATUS_ERROR_INVALID;
293 service_common_destroy(s_info.svc_ctx);
294 DbgPrint("Successfully Finalized\n");
295 return LB_STATUS_SUCCESS;