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