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 <dynamicbox_errno.h>
28 #include <dynamicbox_service.h>
29 #include <dynamicbox_buffer.h>
33 #include "dynamicbox.h"
34 #include "dynamicbox_internal.h"
35 #include "master_rpc.h"
39 #define DEFAULT_TTL 10
40 #define REQUEST_DELAY 10
44 struct packet *packet;
46 void (*ret_cb)(dynamicbox_h handler, const struct packet *result, void *data);
58 struct dlist *cmd_list;
64 static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data);
66 static inline struct command *pop_command(void)
69 struct command *command;
71 l = dlist_nth(s_info.cmd_list, 0);
76 command = dlist_data(l);
77 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
81 static inline struct command *create_command(dynamicbox_h handler, struct packet *packet)
83 struct command *command;
85 command = malloc(sizeof(*command));
87 ErrPrint("Failed to allocate mem for command\n");
91 command->handler = dbox_ref(handler);
92 command->packet = packet_ref(packet);
96 static inline void destroy_command(struct command *command)
98 packet_unref(command->packet);
99 dbox_unref(command->handler, 1);
103 static gboolean cmd_consumer(gpointer user_data)
105 struct command *command;
107 command = pop_command();
109 s_info.cmd_timer = 0;
115 * Item will be deleted in the "done_cb"
117 * item->param be release by the g_dbus_proxy_call
118 * so to use it again from the done_cb function,
119 * increate the reference counter of the item->param
121 if (command->type == TYPE_NOACK) {
122 if (com_core_packet_send_only(client_fd(), command->packet) < 0) {
123 ErrPrint("Failed to send a packet to master\n");
126 destroy_command(command);
128 if (com_core_packet_async_send(client_fd(), command->packet, 0u, done_cb, command) < 0) {
129 ErrPrint("Failed to send a packet to master\n");
130 if (command->ret_cb) {
131 command->ret_cb(command->handler, NULL, command->data);
133 destroy_command(command);
139 static inline void prepend_command(struct command *command)
141 s_info.cmd_list = dlist_prepend(s_info.cmd_list, command);
142 master_rpc_check_and_fire_consumer();
145 void master_rpc_check_and_fire_consumer(void)
147 if (!s_info.cmd_list || s_info.cmd_timer || client_fd() < 0) {
151 s_info.cmd_timer = g_timeout_add(REQUEST_DELAY, cmd_consumer, NULL);
152 if (!s_info.cmd_timer) {
153 ErrPrint("Failed to add timer\n");
157 static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data)
159 struct command *command;
166 * Release resource even if
167 * we failed to finish the method call
170 if (command->ttl > 0) {
171 prepend_command(command);
178 if (packet_get(packet, "i", &ret) != 1) {
179 ErrPrint("Invalid result packet\n");
180 ret = DBOX_STATUS_ERROR_INVALID_PARAMETER;
184 if (command->ret_cb) {
185 command->ret_cb(command->handler, packet, command->data);
188 destroy_command(command);
192 static inline void push_command(struct command *command)
194 s_info.cmd_list = dlist_append(s_info.cmd_list, command);
195 master_rpc_check_and_fire_consumer();
200 * "handler" could be NULL
202 int master_rpc_async_request(dynamicbox_h handler, struct packet *packet, int urgent, void (*ret_cb)(dynamicbox_h handler, const struct packet *result, void *data), void *data)
204 struct command *command;
206 command = create_command(handler, packet);
208 ErrPrint("Failed to create a command\n");
209 packet_unref(packet);
210 return DBOX_STATUS_ERROR_FAULT;
213 command->ret_cb = ret_cb;
214 command->data = data;
215 command->ttl = DEFAULT_TTL;
216 command->type = TYPE_ACK;
219 prepend_command(command);
221 push_command(command);
224 packet_unref(packet);
225 return DBOX_STATUS_ERROR_NONE;
228 int master_rpc_request_only(dynamicbox_h handler, struct packet *packet)
230 struct command *command;
232 command = create_command(handler, packet);
234 ErrPrint("Failed to create a command\n");
235 packet_unref(packet);
236 return DBOX_STATUS_ERROR_FAULT;
239 command->ret_cb = NULL;
240 command->data = NULL;
242 command->type = TYPE_NOACK;
244 push_command(command);
245 packet_unref(packet);
246 return DBOX_STATUS_ERROR_NONE;
249 int master_rpc_clear_fault_package(const char *pkgname)
253 struct command *command;
256 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
259 dlist_foreach_safe(s_info.cmd_list, l, n, command) {
260 if (!command->handler) {
264 if (!strcmp(command->handler->common->pkgname, pkgname)) {
265 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
266 if (command->ret_cb) {
267 command->ret_cb(command->handler, NULL, command->data);
270 destroy_command(command);
277 int master_rpc_clear_all_request(void)
279 struct command *command;
283 dlist_foreach_safe(s_info.cmd_list, l, n, command) {
284 s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
286 if (command->ret_cb) {
287 command->ret_cb(command->handler, NULL, command->data);
290 destroy_command(command);
296 int master_rpc_sync_request(struct packet *packet)
298 struct packet *result;
301 result = com_core_packet_oneshot_send(client_addr(), packet, 0.0f);
303 if (packet_get(result, "i", &ret) != 1) {
304 ErrPrint("Invalid result packet\n");
305 ret = DBOX_STATUS_ERROR_INVALID_PARAMETER;
308 packet_unref(result);
310 ErrPrint("Failed to send a sync request\n");
311 ret = DBOX_STATUS_ERROR_FAULT;
314 packet_unref(packet);