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.
26 #include <com-core_packet.h>
27 #include <livebox-errno.h>
28 #include <livebox-service.h>
33 #include "livebox_internal.h"
34 #include "master_rpc.h"
38 #define DEFAULT_TTL 10
39 #define REQUEST_DELAY 10
43 struct packet *packet;
44 struct livebox *handler;
45 void (*ret_cb)(struct livebox *handler, const struct packet *result, void *data);
57 struct dlist *cmd_list;
63 static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data);
65 static inline struct command *pop_command(void)
68 struct command *command;
70 l = dlist_nth(s_info.cmd_list, 0);
75 command = dlist_data(l);
76 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
80 static inline struct command *create_command(struct livebox *handler, struct packet *packet)
82 struct command *command;
84 command = malloc(sizeof(*command));
86 ErrPrint("Failed to allocate mem for command\n");
90 command->handler = lb_ref(handler);
91 command->packet = packet_ref(packet);
95 static inline void destroy_command(struct command *command)
97 packet_unref(command->packet);
98 lb_unref(command->handler);
102 static gboolean cmd_consumer(gpointer user_data)
104 struct command *command;
106 command = pop_command();
108 s_info.cmd_timer = 0;
114 * Item will be deleted in the "done_cb"
116 * item->param be release by the g_dbus_proxy_call
117 * so to use it again from the done_cb function,
118 * increate the reference counter of the item->param
120 if (command->type == TYPE_NOACK) {
121 if (com_core_packet_send_only(client_fd(), command->packet) < 0) {
122 ErrPrint("Failed to send a packet to master\n");
125 destroy_command(command);
127 if (com_core_packet_async_send(client_fd(), command->packet, 0u, done_cb, command) < 0) {
128 ErrPrint("Failed to send a packet to master\n");
129 if (command->ret_cb) {
130 command->ret_cb(command->handler, NULL, command->data);
132 destroy_command(command);
138 static inline void prepend_command(struct command *command)
140 s_info.cmd_list = dlist_prepend(s_info.cmd_list, command);
141 master_rpc_check_and_fire_consumer();
144 void master_rpc_check_and_fire_consumer(void)
146 if (!s_info.cmd_list || s_info.cmd_timer || client_fd() < 0) {
150 s_info.cmd_timer = g_timeout_add(REQUEST_DELAY, cmd_consumer, NULL);
151 if (!s_info.cmd_timer) {
152 ErrPrint("Failed to add timer\n");
156 static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data)
158 struct command *command;
165 * Release resource even if
166 * we failed to finish the method call
169 if (command->ttl > 0) {
170 prepend_command(command);
177 if (packet_get(packet, "i", &ret) != 1) {
178 ErrPrint("Invalid result packet\n");
179 ret = LB_STATUS_ERROR_INVALID;
183 if (command->ret_cb) {
184 command->ret_cb(command->handler, packet, command->data);
187 destroy_command(command);
191 static inline void push_command(struct command *command)
193 s_info.cmd_list = dlist_append(s_info.cmd_list, command);
194 master_rpc_check_and_fire_consumer();
199 * "handler" could be NULL
201 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)
203 struct command *command;
205 command = create_command(handler, packet);
207 ErrPrint("Failed to create a command\n");
208 packet_unref(packet);
209 return LB_STATUS_ERROR_FAULT;
212 command->ret_cb = ret_cb;
213 command->data = data;
214 command->ttl = DEFAULT_TTL;
215 command->type = TYPE_ACK;
218 prepend_command(command);
220 push_command(command);
223 packet_unref(packet);
224 return LB_STATUS_SUCCESS;
227 int master_rpc_request_only(struct livebox *handler, struct packet *packet)
229 struct command *command;
231 command = create_command(handler, packet);
233 ErrPrint("Failed to create a command\n");
234 packet_unref(packet);
235 return LB_STATUS_ERROR_FAULT;
238 command->ret_cb = NULL;
239 command->data = NULL;
241 command->type = TYPE_NOACK;
243 push_command(command);
244 packet_unref(packet);
245 return LB_STATUS_SUCCESS;
248 int master_rpc_clear_fault_package(const char *pkgname)
252 struct command *command;
255 return LB_STATUS_ERROR_INVALID;
258 dlist_foreach_safe(s_info.cmd_list, l, n, command) {
259 if (!command->handler) {
263 if (!strcmp(command->handler->pkgname, pkgname)) {
264 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
265 if (command->ret_cb) {
266 command->ret_cb(command->handler, NULL, command->data);
269 destroy_command(command);
276 int master_rpc_clear_all_request(void)
278 struct command *command;
282 dlist_foreach_safe(s_info.cmd_list, l, n, command) {
283 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
285 if (command->ret_cb) {
286 command->ret_cb(command->handler, NULL, command->data);
289 destroy_command(command);
295 int master_rpc_sync_request(struct packet *packet)
297 struct packet *result;
300 result = com_core_packet_oneshot_send(client_addr(), packet, 0.0f);
302 if (packet_get(result, "i", &ret) != 1) {
303 ErrPrint("Invalid result packet\n");
304 ret = LB_STATUS_ERROR_INVALID;
307 packet_unref(result);
309 ErrPrint("Failed to send a sync request\n");
310 ret = LB_STATUS_ERROR_FAULT;
313 packet_unref(packet);