Apply coding guide : strcmp
[platform/core/pim/contacts-service.git] / client / ctsvc_client_ipc.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <glib.h>
21 #include <stdlib.h>
22 #include <pims-ipc-data.h>
23
24 #include "ctsvc_client_ipc.h"
25
26 #include "ctsvc_internal.h"
27 #include "ctsvc_list.h"
28 #include "ctsvc_record.h"
29 #include "ctsvc_query.h"
30 #include "ctsvc_inotify.h"
31
32 #include "ctsvc_ipc_define.h"
33 #include "ctsvc_ipc_marshal.h"
34 #include "ctsvc_view.h"
35 #include "ctsvc_mutex.h"
36
37 static __thread pims_ipc_h __contacts_ipc = NULL;
38 static pims_ipc_h __contacts_global_ipc = NULL;
39
40 static __thread int __contacts_change_version = 0;
41 static int __contacts_global_change_version = 0;
42
43 int ctsvc_ipc_connect_on_thread(void)
44 {
45         int ret = CONTACTS_ERROR_NONE;
46         pims_ipc_data_h outdata = NULL;
47
48         // ipc create
49         if (__contacts_ipc == NULL) {
50                 char sock_file[CTSVC_PATH_MAX_LEN] = {0};
51                 snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/.%s", getuid(), CTSVC_IPC_SERVICE);
52                 __contacts_ipc = pims_ipc_create(sock_file);
53                 if (__contacts_ipc == NULL) {
54                         if (errno == EACCES) {
55                                 CTS_ERR("pims_ipc_create() Fail(%d)", CONTACTS_ERROR_PERMISSION_DENIED);
56                                 return CONTACTS_ERROR_PERMISSION_DENIED;
57                         }
58                         else {
59                                 CTS_ERR("pims_ipc_create() Fail(%d)", CONTACTS_ERROR_IPC_NOT_AVALIABLE);
60                                 return CONTACTS_ERROR_IPC_NOT_AVALIABLE;
61                         }
62                 }
63         }
64         else {
65                 CTS_DBG("contacts already connected");
66                 return CONTACTS_ERROR_NONE;
67         }
68
69         // ipc call
70         if (pims_ipc_call(__contacts_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CONNECT, NULL, &outdata) != 0) {
71                 CTS_ERR("pims_ipc_call Fail");
72                 ret = CONTACTS_ERROR_IPC;
73                 goto DATA_FREE;
74         }
75
76         if (outdata) {
77                 unsigned int size = 0;
78                 ret = *(int*) pims_ipc_data_get(outdata,&size);
79
80                 pims_ipc_data_destroy(outdata);
81
82                 if (ret != CONTACTS_ERROR_NONE) {
83                         CTS_ERR("ctsvc_ipc_server_connect return(%d)", ret);
84                         goto DATA_FREE;
85                 }
86         }
87
88         return ret;
89
90 DATA_FREE:
91         pims_ipc_destroy(__contacts_ipc);
92         __contacts_ipc = NULL;
93
94         return ret;
95 }
96
97 int ctsvc_ipc_disconnect_on_thread(void)
98 {
99         int ret = CONTACTS_ERROR_NONE;
100         pims_ipc_data_h outdata = NULL;
101
102         RETVM_IF(__contacts_ipc == NULL, CONTACTS_ERROR_IPC, "contacts not connected");
103
104         if (pims_ipc_call(__contacts_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_DISCONNECT, NULL, &outdata) != 0) {
105                 CTS_ERR("pims_ipc_call Fail");
106                 return CONTACTS_ERROR_IPC;
107         }
108
109         if (outdata) {
110                 unsigned int size = 0;
111                 ret = *(int*) pims_ipc_data_get(outdata,&size);
112                 pims_ipc_data_destroy(outdata);
113
114                 if (ret != CONTACTS_ERROR_NONE)
115                         CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc didn't destroyed!!!(%d)", ret);
116
117                 pims_ipc_destroy(__contacts_ipc);
118                 __contacts_ipc = NULL;
119         }
120         else {
121                 CTS_ERR("pims_ipc_call out data is NULL");
122                 return CONTACTS_ERROR_IPC;
123         }
124
125         return ret;
126 }
127
128 pims_ipc_h ctsvc_get_ipc_handle()
129 {
130         if (__contacts_ipc == NULL) {
131                 if (__contacts_global_ipc == NULL) {
132                         CTS_ERR("IPC haven't been initialized yet.");
133                         return NULL;
134                 }
135                 CTS_DBG("fallback to global ipc channel");
136                 return __contacts_global_ipc;
137         }
138
139         return __contacts_ipc;
140 }
141
142 bool ctsvc_ipc_is_busy()
143 {
144         bool ret = false;
145
146         if (__contacts_ipc != NULL) {
147                 ret = pims_ipc_is_call_in_progress(__contacts_ipc);
148                 if (ret)
149                         CTS_ERR("thread local ipc channel is busy.");
150         }
151         else {
152                 ret = pims_ipc_is_call_in_progress(__contacts_global_ipc);
153                 if (ret)
154                         CTS_ERR("global ipc channel is busy.");
155         }
156
157         return ret;
158 }
159
160 int ctsvc_ipc_connect(void)
161 {
162         int ret = CONTACTS_ERROR_NONE;
163         pims_ipc_data_h outdata = NULL;
164
165         // ipc create
166         if (__contacts_global_ipc == NULL) {
167                 char sock_file[CTSVC_PATH_MAX_LEN] = {0};
168                 snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/.%s", getuid(), CTSVC_IPC_SERVICE);
169                 __contacts_global_ipc = pims_ipc_create(sock_file);
170                 if (__contacts_global_ipc == NULL) {
171                         if (errno == EACCES) {
172                                 CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_create() Fail(%d)", CONTACTS_ERROR_PERMISSION_DENIED);
173                                 return CONTACTS_ERROR_PERMISSION_DENIED;
174                         }
175                         else {
176                                 CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_create() Fail(%d)", CONTACTS_ERROR_IPC_NOT_AVALIABLE);
177                                 return CONTACTS_ERROR_IPC_NOT_AVALIABLE;
178                         }
179                 }
180         }
181         else {
182                 CTS_DBG("[GLOBAL_IPC_CHANNEL] contacts already connected");
183                 return CONTACTS_ERROR_NONE;
184         }
185
186         // ipc call
187         if (pims_ipc_call(__contacts_global_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CONNECT, NULL, &outdata) != 0) {
188                 CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_call Fail");
189                 ret = CONTACTS_ERROR_IPC;
190                 goto DATA_FREE;
191         }
192
193         if (outdata) {
194                 unsigned int size = 0;
195                 ret = *(int*) pims_ipc_data_get(outdata,&size);
196                 pims_ipc_data_destroy(outdata);
197
198                 if (ret != CONTACTS_ERROR_NONE) {
199                         CTS_ERR("ctsvc_ipc_server_connect return(%d)", ret);
200                         goto DATA_FREE;
201                 }
202         }
203         return ret;
204
205 DATA_FREE:
206         pims_ipc_destroy(__contacts_global_ipc);
207         __contacts_global_ipc = NULL;
208         return ret;
209 }
210
211
212 int ctsvc_ipc_disconnect(void)
213 {
214         int ret = CONTACTS_ERROR_NONE;
215         pims_ipc_data_h outdata = NULL;
216
217         RETVM_IF(__contacts_global_ipc == NULL, CONTACTS_ERROR_IPC, "[GLOBAL_IPC_CHANNEL] contacts not connected");
218
219         if (pims_ipc_call(__contacts_global_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_DISCONNECT, NULL, &outdata) != 0) {
220                 CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_call Fail");
221                 return CONTACTS_ERROR_IPC;
222         }
223
224         if (outdata) {
225                 unsigned int size = 0;
226                 ret = *(int*) pims_ipc_data_get(outdata,&size);
227                 pims_ipc_data_destroy(outdata);
228
229                 if (ret != CONTACTS_ERROR_NONE)
230                         CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc didn't destroyed!!!(%d)", ret);
231
232                 pims_ipc_destroy(__contacts_global_ipc);
233                 __contacts_global_ipc = NULL;
234         }
235         else {
236                 CTS_ERR("pims_ipc_call out data is NULL");
237                 return CONTACTS_ERROR_IPC;
238         }
239
240         return ret;
241 }
242
243 static void __ctsvc_ipc_lock()
244 {
245         if (__contacts_ipc == NULL)
246                 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_CALL);
247 }
248
249 static void __ctsvc_ipc_unlock(void)
250 {
251         if (__contacts_ipc == NULL)
252                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_CALL);
253 }
254
255 int ctsvc_ipc_call(char *module, char *function, pims_ipc_h data_in, pims_ipc_data_h *data_out)
256 {
257         pims_ipc_h ipc_handle = ctsvc_get_ipc_handle();
258
259         __ctsvc_ipc_lock();
260
261         int ret = pims_ipc_call(ipc_handle, module, function, data_in, data_out);
262
263         __ctsvc_ipc_unlock();
264
265         return ret;
266 }
267
268 void ctsvc_client_ipc_set_change_version(int version)
269 {
270         if (__contacts_ipc == NULL) {
271                 __contacts_global_change_version = version;
272                 CTS_DBG("change_version = %d", version);
273                 return;
274         }
275         __contacts_change_version = version;
276         CTS_DBG("change_version = %d", version);
277 }
278
279 int ctsvc_client_ipc_get_change_version(void)
280 {
281         if (__contacts_ipc == NULL)
282                 return __contacts_global_change_version;
283
284         return __contacts_change_version;
285 }
286
287 int ctsvc_ipc_client_check_permission(int permission, bool *result)
288 {
289         pims_ipc_data_h indata = NULL;
290         pims_ipc_data_h outdata = NULL;
291         int ret;
292
293         if (result)
294                 *result = false;
295
296         indata = pims_ipc_data_create(0);
297         if (indata == NULL) {
298                 CTS_ERR("ipc data created fail !");
299                 return CONTACTS_ERROR_OUT_OF_MEMORY;
300         }
301
302         ret = ctsvc_ipc_marshal_int(permission, indata);
303         if (ret != CONTACTS_ERROR_NONE) {
304                 CTS_ERR("marshal fail");
305                 pims_ipc_data_destroy(indata);
306                 return ret;
307         }
308
309         if (ctsvc_ipc_call(CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CHECK_PERMISSION, indata, &outdata) != 0) {
310                 CTS_ERR("ctsvc_ipc_call Fail");
311                 pims_ipc_data_destroy(indata);
312                 return CONTACTS_ERROR_IPC;
313         }
314
315         pims_ipc_data_destroy(indata);
316
317         if (outdata) {
318                 unsigned int size = 0;
319                 ret = *(int*) pims_ipc_data_get(outdata,&size);
320
321                 if (ret == CONTACTS_ERROR_NONE) {
322                         if (result)
323                                 *result = *(bool*) pims_ipc_data_get(outdata, &size);
324                 }
325                 pims_ipc_data_destroy(outdata);
326         }
327
328         return ret;
329 }
330