2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://www.tizenopensource.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.
26 #include <com-core_packet.h>
27 #include <livebox-errno.h>
32 #include "livebox_internal.h"
33 #include "master_rpc.h"
37 #define DEFAULT_TTL 10
38 #define REQUEST_DELAY 10
42 struct packet *packet;
43 struct livebox *handler;
44 void (*ret_cb)(struct livebox *handler, const struct packet *result, void *data);
56 struct dlist *cmd_list;
62 static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data);
64 static inline struct command *pop_command(void)
67 struct command *command;
69 l = dlist_nth(s_info.cmd_list, 0);
73 command = dlist_data(l);
74 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
78 static inline struct command *create_command(struct livebox *handler, struct packet *packet)
80 struct command *command;
82 command = malloc(sizeof(*command));
84 ErrPrint("Failed to allocate mem for command\n");
88 command->handler = lb_ref(handler);
89 command->packet = packet_ref(packet);
93 static inline void destroy_command(struct command *command)
95 packet_unref(command->packet);
96 lb_unref(command->handler);
100 static gboolean cmd_consumer(gpointer user_data)
102 struct command *command;
104 command = pop_command();
106 s_info.cmd_timer = 0;
112 * Item will be deleted in the "done_cb"
114 * item->param be release by the g_dbus_proxy_call
115 * so to use it again from the done_cb function,
116 * increate the reference counter of the item->param
118 if (command->type == TYPE_NOACK) {
119 if (com_core_packet_send_only(client_fd(), command->packet) < 0)
120 ErrPrint("Failed to send a packet to master\n");
122 destroy_command(command);
124 if (com_core_packet_async_send(client_fd(), command->packet, 0u, done_cb, command) < 0) {
125 DbgPrint("Failed to send a packet to master\n");
127 command->ret_cb(command->handler, NULL, command->data);
128 destroy_command(command);
134 static inline void prepend_command(struct command *command)
136 s_info.cmd_list = dlist_prepend(s_info.cmd_list, command);
137 master_rpc_check_and_fire_consumer();
140 void master_rpc_check_and_fire_consumer(void)
142 if (!s_info.cmd_list || s_info.cmd_timer || client_fd() < 0)
145 s_info.cmd_timer = g_timeout_add(REQUEST_DELAY, cmd_consumer, NULL);
146 if (!s_info.cmd_timer)
147 ErrPrint("Failed to add timer\n");
150 static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data)
152 struct command *command;
159 * Release resource even if
160 * we failed to finish the method call
163 if (command->ttl > 0) {
164 prepend_command(command);
171 if (packet_get(packet, "i", &ret) != 1) {
172 ErrPrint("Invalid result packet\n");
173 ret = LB_STATUS_ERROR_INVALID;
176 DbgPrint("[%s] Returns: %d\n", packet_command(packet), ret);
180 command->ret_cb(command->handler, packet, command->data);
182 destroy_command(command);
186 static inline void push_command(struct command *command)
188 s_info.cmd_list = dlist_append(s_info.cmd_list, command);
189 master_rpc_check_and_fire_consumer();
194 * "handler" could be NULL
196 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)
198 struct command *command;
200 command = create_command(handler, packet);
202 ErrPrint("Failed to create a command\n");
204 ret_cb(handler, NULL, data);
206 packet_unref(packet);
207 return LB_STATUS_ERROR_FAULT;
210 command->ret_cb = ret_cb;
211 command->data = data;
212 command->ttl = DEFAULT_TTL;
213 command->type = TYPE_ACK;
216 prepend_command(command);
218 push_command(command);
220 packet_unref(packet);
221 return LB_STATUS_SUCCESS;
224 int master_rpc_request_only(struct livebox *handler, struct packet *packet)
226 struct command *command;
228 command = create_command(handler, packet);
230 ErrPrint("Failed to create a command\n");
231 packet_unref(packet);
232 return LB_STATUS_ERROR_FAULT;
235 command->ret_cb = NULL;
236 command->data = NULL;
238 command->type = TYPE_NOACK;
240 push_command(command);
241 packet_unref(packet);
242 return LB_STATUS_SUCCESS;
245 int master_rpc_clear_fault_package(const char *pkgname)
249 struct command *command;
252 return LB_STATUS_ERROR_INVALID;
254 DbgPrint("Clear requests of the fault package(%s)\n", pkgname);
256 dlist_foreach_safe(s_info.cmd_list, l, n, command) {
257 if (!command->handler)
260 if (!strcmp(command->handler->pkgname, pkgname)) {
261 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
263 command->ret_cb(command->handler, NULL, command->data);
265 destroy_command(command);
272 int master_rpc_clear_all_request(void)
274 struct command *command;
278 DbgPrint("Clear all pended requests\n");
280 dlist_foreach_safe(s_info.cmd_list, l, n, command) {
281 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
284 command->ret_cb(command->handler, NULL, command->data);
286 destroy_command(command);
292 int master_rpc_sync_request(struct packet *packet)
294 struct packet *result;
297 result = com_core_packet_oneshot_send(client_addr(), packet, 0.0f);
299 if (packet_get(result, "i", &ret) != 1) {
300 ErrPrint("Invalid result packet\n");
301 ret = LB_STATUS_ERROR_INVALID;
304 packet_unref(result);
306 ErrPrint("Failed to send a sync request\n");
307 ret = LB_STATUS_ERROR_FAULT;
310 packet_unref(packet);