Change the LOG_TAG
[platform/framework/web/livebox-viewer.git] / src / master_rpc.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (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://www.tizenopensource.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 <gio/gio.h>
19 #include <errno.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <dlog.h>
24
25 #include <packet.h>
26 #include <com-core_packet.h>
27
28 #include "debug.h"
29 #include "dlist.h"
30 #include "livebox.h"
31 #include "livebox_internal.h"
32 #include "master_rpc.h"
33 #include "client.h"
34 #include "util.h"
35
36 #define DEFAULT_TTL 10
37 #define REQUEST_DELAY 10
38
39 struct command {
40         int ttl;
41         struct packet *packet;
42         struct livebox *handler;
43         void (*ret_cb)(struct livebox *handler, const struct packet *result, void *data);
44         void *data;
45         enum {
46                 TYPE_ACK,
47                 TYPE_NOACK,
48         } type;
49 };
50
51 int errno;
52
53 static struct {
54         guint cmd_timer;
55         struct dlist *cmd_list;
56 } s_info = {
57         .cmd_timer = 0,
58         .cmd_list = NULL,
59 };
60
61 static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data);
62
63 static inline struct command *pop_command(void)
64 {
65         struct dlist *l;
66         struct command *command;
67
68         l = dlist_nth(s_info.cmd_list, 0);
69         if (!l)
70                 return NULL;
71
72         command = dlist_data(l);
73         s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
74         return command;
75 }
76
77 static inline struct command *create_command(struct livebox *handler, struct packet *packet)
78 {
79         struct command *command;
80
81         command = malloc(sizeof(*command));
82         if (!command) {
83                 ErrPrint("Failed to allocate mem for command\n");
84                 return NULL;
85         }
86
87         command->handler = lb_ref(handler);
88         command->packet = packet_ref(packet);
89         return command;
90 }
91
92 static inline void destroy_command(struct command *command)
93 {
94         packet_unref(command->packet);
95         lb_unref(command->handler);
96         free(command);
97 }
98
99 static gboolean cmd_consumer(gpointer user_data)
100 {
101         struct command *command;
102
103         command = pop_command();
104         if (!command) {
105                 s_info.cmd_timer = 0;
106                 return FALSE;
107         }
108
109         /*!
110          * \NOTE:
111          * Item will be deleted in the "done_cb"
112          *
113          * item->param be release by the g_dbus_proxy_call
114          * so to use it again from the done_cb function,
115          * increate the reference counter of the item->param
116          */
117         if (command->type == TYPE_NOACK) {
118                 if (com_core_packet_send_only(client_fd(), command->packet) < 0)
119                         ErrPrint("Failed to send a packet to master\n");
120
121                 destroy_command(command);
122         } else {
123                 if (com_core_packet_async_send(client_fd(), command->packet, 0u, done_cb, command) < 0) {
124                         DbgPrint("Failed to send a packet to master\n");
125                         if (command->ret_cb)
126                                 command->ret_cb(command->handler, NULL, command->data);
127                         destroy_command(command);
128                 }
129         }
130         return TRUE;
131 }
132
133 static inline void prepend_command(struct command *command)
134 {
135         s_info.cmd_list = dlist_prepend(s_info.cmd_list, command);
136         master_rpc_check_and_fire_consumer();
137 }
138
139 void master_rpc_check_and_fire_consumer(void)
140 {
141         if (!s_info.cmd_list || s_info.cmd_timer || client_fd() < 0)
142                 return;
143
144         s_info.cmd_timer = g_timeout_add(REQUEST_DELAY, cmd_consumer, NULL);
145         if (!s_info.cmd_timer)
146                 ErrPrint("Failed to add timer\n");
147 }
148
149 static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data)
150 {
151         struct command *command;
152         int ret;
153
154         command = data;
155
156         if (!packet) {
157                 /*! \NOTE:
158                  * Release resource even if
159                  * we failed to finish the method call
160                  */
161                 command->ttl--;
162                 if (command->ttl > 0) {
163                         prepend_command(command);
164                         return 0;
165                 }
166
167                 goto out;
168         }
169
170         if (packet_get(packet, "i", &ret) != 1) {
171                 ErrPrint("Invalid result packet\n");
172                 ret = -EINVAL;
173         }
174
175         DbgPrint("[%s] Returns: %d\n", packet_command(packet), ret);
176
177 out:
178         if (command->ret_cb)
179                 command->ret_cb(command->handler, packet, command->data);
180
181         destroy_command(command);
182         return 0;
183 }
184
185 static inline void push_command(struct command *command)
186 {
187         s_info.cmd_list = dlist_append(s_info.cmd_list, command);
188         master_rpc_check_and_fire_consumer();
189 }
190
191 /*!
192  * \note
193  * "handler" could be NULL
194  */
195 int master_rpc_async_request(struct livebox *handler, struct packet *packet, int urgent, void (*ret_cb)(struct livebox *handler, const struct packet *result, void *data), void *data)
196 {
197         struct command *command;
198
199         command = create_command(handler, packet);
200         if (!command) {
201                 ErrPrint("Failed to create a command\n");
202                 if (ret_cb)
203                         ret_cb(handler, NULL, data);
204
205                 packet_unref(packet);
206                 return -EFAULT;
207         }
208
209         command->ret_cb = ret_cb;
210         command->data = data;
211         command->ttl = DEFAULT_TTL;
212         command->type = TYPE_ACK;
213
214         if (urgent)
215                 prepend_command(command);
216         else
217                 push_command(command);
218
219         packet_unref(packet);
220         return 0;
221 }
222
223 int master_rpc_request_only(struct livebox *handler, struct packet *packet)
224 {
225         struct command *command;
226
227         command = create_command(handler, packet);
228         if (!command) {
229                 ErrPrint("Failed to create a command\n");
230                 packet_unref(packet);
231                 return -EFAULT;
232         }
233
234         command->ret_cb = NULL;
235         command->data = NULL;
236         command->ttl = 0;
237         command->type = TYPE_NOACK;
238
239         push_command(command);
240         packet_unref(packet);
241         return 0;
242 }
243
244 int master_rpc_clear_fault_package(const char *pkgname)
245 {
246         struct dlist *l;
247         struct dlist *n;
248         struct command *command;
249
250         if (!pkgname)
251                 return -EINVAL;
252
253         DbgPrint("Clear requests of the fault package(%s)\n", pkgname);
254
255         dlist_foreach_safe(s_info.cmd_list, l, n, command) {
256                 if (!command->handler)
257                         continue;
258
259                 if (!strcmp(command->handler->pkgname, pkgname)) {
260                         s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
261                         if (command->ret_cb)
262                                 command->ret_cb(command->handler, NULL, command->data);
263
264                         destroy_command(command);
265                 }
266         }
267
268         return 0;
269 }
270
271 int master_rpc_clear_all_request(void)
272 {
273         struct command *command;
274         struct dlist *l;
275         struct dlist *n;
276
277         DbgPrint("Clear all pended requests\n");
278
279         dlist_foreach_safe(s_info.cmd_list, l, n, command) {
280                 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
281
282                 if (command->ret_cb)
283                         command->ret_cb(command->handler, NULL, command->data);
284
285                 destroy_command(command);
286         }
287
288         return 0;
289 }
290
291 int master_rpc_sync_request(struct packet *packet)
292 {
293         struct packet *result;
294         int ret;
295
296         result = com_core_packet_oneshot_send(client_addr(), packet, 0.0f);
297         if (result) {
298                 if (packet_get(result, "i", &ret) != 1) {
299                         ErrPrint("Invalid result packet\n");
300                         ret = -EINVAL;
301                 }
302
303                 packet_unref(result);
304         } else {
305                 ErrPrint("Failed to send a sync request\n");
306                 ret = -EFAULT;
307         }
308
309         packet_unref(packet);
310         return ret;
311 }
312
313 /* End of a file */