tizen 2.3 release
[apps/livebox/data-provider-master.git] / src / client_rpc.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
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
7  *
8  * http://floralicense.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 <errno.h>
19
20 #include <Eina.h>
21 #include <Ecore.h>
22
23 #include <dlog.h>
24 #include <com-core_packet.h>
25 #include <packet.h>
26 #include <dynamicbox_errno.h>
27 #include <dynamicbox_conf.h>
28 #include <dynamicbox_service.h>
29
30 #include "client_life.h"
31 #include "instance.h"
32 #include "client_rpc.h"
33 #include "debug.h"
34 #include "conf.h"
35 #include "util.h"
36
37 #define RPC_TAG "rpc"
38
39 /*!
40  * \note
41  * Static component information structure.
42  */
43 static struct info {
44         Eina_List *command_list; /*!< Packet Q: Before sending the request, all request commands will stay here */
45         Ecore_Timer *command_consumer; /*!< This timer will consuming the command Q. sending them to the specified client */
46 } s_info = {
47         .command_list = NULL,
48         .command_consumer = NULL,
49 };
50
51 struct client_rpc {
52         int handle; /*!< Handler for communication with client */
53 };
54
55 struct command {
56         struct packet *packet;
57         struct client_node *client; /*!< Target client. who should receive this command */
58 };
59
60 /*!
61  * \brief
62  * Creating or Destroying command object
63  */
64 static inline struct command *create_command(struct client_node *client, struct packet *packet)
65 {
66         struct command *command;
67
68         command = calloc(1, sizeof(*command));
69         if (!command) {
70                 ErrPrint("Heap: %s\n", strerror(errno));
71                 return NULL;
72         }
73
74         command->packet = packet_ref(packet);
75         command->client = client_ref(client);
76
77         return command;
78 }
79
80 static inline void destroy_command(struct command *command)
81 {
82         client_unref(command->client);
83         packet_unref(command->packet);
84         DbgFree(command);
85 }
86
87 static inline int count_command(void)
88 {
89         return eina_list_count(s_info.command_list);
90 }
91
92 static inline struct command *pop_command(void)
93 {
94         struct command *command;
95
96         command = eina_list_nth(s_info.command_list, 0);
97         if (!command) {
98                 return NULL;
99         }
100
101         s_info.command_list = eina_list_remove(s_info.command_list, command);
102         return command;
103 }
104
105 static Eina_Bool command_consumer_cb(void *data)
106 {
107         struct command *command;
108         struct client_rpc *rpc;
109         int ret;
110
111         command = pop_command();
112         if (!command) {
113                 s_info.command_consumer = NULL;
114                 return ECORE_CALLBACK_CANCEL;
115         }
116
117         if (!command->client) {
118                 DbgPrint("Has no client\n");
119                 goto out;
120         }
121
122         if (client_is_faulted(command->client)) {
123                 ErrPrint("Client[%p] is faulted, discard command\n", command->client);
124                 goto out;
125         }
126
127         rpc = client_data(command->client, RPC_TAG);
128         if (!rpc) {
129                 ErrPrint("Client is not activated\n");
130                 goto out;
131         }
132
133         if (rpc->handle < 0) {
134                 DbgPrint("RPC is not initialized\n");
135                 goto out;
136         }
137
138         ret = com_core_packet_send_only(rpc->handle, command->packet);
139         if (ret < 0) {
140                 ErrPrint("Failed to send packet %d\n", ret);
141         }
142
143 out:
144         destroy_command(command);
145         return ECORE_CALLBACK_RENEW;
146 }
147
148 static inline void push_command(struct command *command)
149 {
150         s_info.command_list = eina_list_append(s_info.command_list, command);
151
152         if (s_info.command_consumer) {
153                 return;
154         }
155
156         s_info.command_consumer = ecore_timer_add(DYNAMICBOX_CONF_PACKET_TIME, command_consumer_cb, NULL);
157         if (!s_info.command_consumer) {
158                 ErrPrint("Failed to add command consumer\n");
159                 s_info.command_list = eina_list_remove(s_info.command_list, command);
160                 destroy_command(command);
161         }
162 }
163
164 HAPI int client_rpc_async_request(struct client_node *client, struct packet *packet)
165 {
166         struct command *command;
167         struct client_rpc *rpc;
168
169         if (!client || !packet) {
170                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
171         }
172
173         if (client_is_faulted(client)) {
174                 ErrPrint("Client[%p] is faulted\n", client);
175                 packet_unref(packet);
176                 return DBOX_STATUS_ERROR_FAULT;
177         }
178
179         rpc = client_data(client, RPC_TAG);
180         if (!rpc) {
181                 ErrPrint("Client[%p] is not ready for communication (%s)\n", client, packet_command(packet));
182         }
183
184         command = create_command(client, packet);
185         if (!command) {
186                 packet_unref(packet);
187                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
188         }
189
190         push_command(command);
191         packet_unref(packet);
192         return DBOX_STATUS_ERROR_NONE;
193 }
194
195 static int deactivated_cb(struct client_node *client, void *data)
196 {
197         struct client_rpc *rpc;
198         struct command *command;
199         Eina_List *l;
200         Eina_List *n;
201
202         rpc = client_data(client, RPC_TAG);
203         if (!rpc) {
204                 ErrPrint("client is not valid\n");
205                 return DBOX_STATUS_ERROR_NONE;
206         }
207
208         DbgPrint("Reset handle for %d\n", client_pid(client));
209         rpc->handle = -1;
210
211         DbgPrint("Begin: Destroying command\n");
212         EINA_LIST_FOREACH_SAFE(s_info.command_list, l, n, command) {
213                 if (command->client == client) {
214                         s_info.command_list = eina_list_remove(s_info.command_list, command);
215                         destroy_command(command);
216                 }
217         }
218         DbgPrint("End: Destroying command\n");
219
220         return DBOX_STATUS_ERROR_NONE;
221 }
222
223 HAPI int client_rpc_init(struct client_node *client, int handle)
224 {
225         struct client_rpc *rpc;
226         int ret;
227
228         rpc = calloc(1, sizeof(*rpc));
229         if (!rpc) {
230                 ErrPrint("Heap: %s\n", strerror(errno));
231                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
232         }
233
234         ret = client_set_data(client, RPC_TAG, rpc);
235         if (ret < 0) {
236                 ErrPrint("Failed to set \"rpc\" for client\n");
237                 DbgFree(rpc);
238                 return ret;
239         }
240
241         DbgPrint("CLIENT: New handle assigned for %d, %d (old: %d)\n", client_pid(client), handle, rpc->handle);
242         rpc->handle = handle;
243
244         ret = client_event_callback_add(client, CLIENT_EVENT_DEACTIVATE, deactivated_cb, NULL);
245         if (ret < 0) {
246                 struct client_rpc *weird;
247
248                 weird = client_del_data(client, RPC_TAG);
249                 if (weird != rpc) {
250                         ErrPrint("What happens? (%p <> %p)\n", weird, rpc);
251                 }
252                 DbgFree(rpc);
253         }
254
255         return ret;
256 }
257
258 HAPI int client_rpc_fini(struct client_node *client)
259 {
260         struct client_rpc *rpc;
261
262         rpc = client_del_data(client, RPC_TAG);
263         if (!rpc) {
264                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
265         }
266
267         client_event_callback_del(client, CLIENT_EVENT_DEACTIVATE, deactivated_cb, NULL);
268         DbgFree(rpc);
269         return DBOX_STATUS_ERROR_NONE;
270 }
271
272 HAPI int client_rpc_handle(struct client_node *client)
273 {
274         struct client_rpc *rpc;
275
276         rpc = client_data(client, RPC_TAG);
277         if (!rpc) {
278                 DbgPrint("Client has no RPC\n");
279                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
280         }
281
282         return rpc->handle;
283 }
284
285 /* End of a file */