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>
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);
74 command = dlist_data(l);
75 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
79 static inline struct command *create_command(struct livebox *handler, struct packet *packet)
81 struct command *command;
83 command = malloc(sizeof(*command));
85 ErrPrint("Failed to allocate mem for command\n");
89 command->handler = lb_ref(handler);
90 command->packet = packet_ref(packet);
94 static inline void destroy_command(struct command *command)
96 packet_unref(command->packet);
97 lb_unref(command->handler);
101 static gboolean cmd_consumer(gpointer user_data)
103 struct command *command;
105 command = pop_command();
107 s_info.cmd_timer = 0;
113 * Item will be deleted in the "done_cb"
115 * item->param be release by the g_dbus_proxy_call
116 * so to use it again from the done_cb function,
117 * increate the reference counter of the item->param
119 if (command->type == TYPE_NOACK) {
120 if (com_core_packet_send_only(client_fd(), command->packet) < 0) {
121 ErrPrint("Failed to send a packet to master\n");
124 destroy_command(command);
126 if (com_core_packet_async_send(client_fd(), command->packet, 0u, done_cb, command) < 0) {
127 ErrPrint("Failed to send a packet to master\n");
128 if (command->ret_cb) {
129 command->ret_cb(command->handler, NULL, command->data);
131 destroy_command(command);
137 static inline void prepend_command(struct command *command)
139 s_info.cmd_list = dlist_prepend(s_info.cmd_list, command);
140 master_rpc_check_and_fire_consumer();
143 void master_rpc_check_and_fire_consumer(void)
145 if (!s_info.cmd_list || s_info.cmd_timer || client_fd() < 0) {
149 s_info.cmd_timer = g_timeout_add(REQUEST_DELAY, cmd_consumer, NULL);
150 if (!s_info.cmd_timer) {
151 ErrPrint("Failed to add timer\n");
155 static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data)
157 struct command *command;
164 * Release resource even if
165 * we failed to finish the method call
168 if (command->ttl > 0) {
169 prepend_command(command);
176 if (packet_get(packet, "i", &ret) != 1) {
177 ErrPrint("Invalid result packet\n");
178 ret = LB_STATUS_ERROR_INVALID;
182 if (command->ret_cb) {
183 command->ret_cb(command->handler, packet, command->data);
186 destroy_command(command);
190 static inline void push_command(struct command *command)
192 s_info.cmd_list = dlist_append(s_info.cmd_list, command);
193 master_rpc_check_and_fire_consumer();
198 * "handler" could be NULL
200 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)
202 struct command *command;
204 command = create_command(handler, packet);
206 ErrPrint("Failed to create a command\n");
207 packet_unref(packet);
208 return LB_STATUS_ERROR_FAULT;
211 command->ret_cb = ret_cb;
212 command->data = data;
213 command->ttl = DEFAULT_TTL;
214 command->type = TYPE_ACK;
217 prepend_command(command);
219 push_command(command);
222 packet_unref(packet);
223 return LB_STATUS_SUCCESS;
226 int master_rpc_request_only(struct livebox *handler, struct packet *packet)
228 struct command *command;
230 command = create_command(handler, packet);
232 ErrPrint("Failed to create a command\n");
233 packet_unref(packet);
234 return LB_STATUS_ERROR_FAULT;
237 command->ret_cb = NULL;
238 command->data = NULL;
240 command->type = TYPE_NOACK;
242 push_command(command);
243 packet_unref(packet);
244 return LB_STATUS_SUCCESS;
247 int master_rpc_clear_fault_package(const char *pkgname)
251 struct command *command;
254 return LB_STATUS_ERROR_INVALID;
257 dlist_foreach_safe(s_info.cmd_list, l, n, command) {
258 if (!command->handler) {
262 if (!strcmp(command->handler->pkgname, pkgname)) {
263 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
264 if (command->ret_cb) {
265 command->ret_cb(command->handler, NULL, command->data);
268 destroy_command(command);
275 int master_rpc_clear_all_request(void)
277 struct command *command;
281 dlist_foreach_safe(s_info.cmd_list, l, n, command) {
282 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
284 if (command->ret_cb) {
285 command->ret_cb(command->handler, NULL, command->data);
288 destroy_command(command);
294 int master_rpc_sync_request(struct packet *packet)
296 struct packet *result;
299 result = com_core_packet_oneshot_send(client_addr(), packet, 0.0f);
301 if (packet_get(result, "i", &ret) != 1) {
302 ErrPrint("Invalid result packet\n");
303 ret = LB_STATUS_ERROR_INVALID;
306 packet_unref(result);
308 ErrPrint("Failed to send a sync request\n");
309 ret = LB_STATUS_ERROR_FAULT;
312 packet_unref(packet);