Apply coding guide : strcmp
[platform/core/pim/contacts-service.git] / client / ctsvc_client_noti.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 <pims-ipc.h>
21 #include <pims-ipc-svc.h>
22 #include <pims-ipc-data.h>
23
24 #include "contacts.h"
25 #include "ctsvc_internal.h"
26 #include "ctsvc_ipc_define.h"
27 #include "ctsvc_mutex.h"
28 #include "ctsvc_client_ipc.h"
29 #include "contacts_extension.h"
30
31 typedef struct
32 {
33         contacts_db_change_cb_with_info cb;
34         void *user_data;
35 }db_callback_info_s;
36
37 typedef struct
38 {
39         char *view_uri;
40         GSList *callbacks;
41 }subscribe_info_s;
42
43 static int __ipc_pubsub_ref = 0;
44 static pims_ipc_h __ipc = NULL;
45 static GSList *__db_change_subscribe_list = NULL;
46
47 static void __ctsvc_db_subscriber_callback(pims_ipc_h ipc, pims_ipc_data_h data, void *user_data)
48 {
49         unsigned int size = 0;
50         char *str = NULL;
51         subscribe_info_s *info = user_data;
52
53         if (data)
54                 str = (char*)pims_ipc_data_get(data, &size);
55
56         if (!str) {
57                 CTS_ERR("There is no changed data");
58                 return;
59         }
60
61         if (info) {
62                 GSList *l;
63                 for (l = info->callbacks;l;l=l->next) {
64                         db_callback_info_s *cb_info = l->data;
65                         if (cb_info->cb) {
66                                 cb_info->cb(info->view_uri, str, cb_info->user_data);
67                         }
68                 }
69         }
70 }
71
72 // This API should be called in CTS_MUTEX_PIMS_IPC_PUBSUB mutex
73 pims_ipc_h ctsvc_ipc_get_handle_for_change_subsciption()
74 {
75         return __ipc;
76 }
77
78 int ctsvc_ipc_create_for_change_subscription()
79 {
80         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
81
82         if (0 < __ipc_pubsub_ref) {
83                 __ipc_pubsub_ref++;
84                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
85                 return CONTACTS_ERROR_NONE;
86         }
87
88         if (!__ipc) {
89                 char sock_file[CTSVC_PATH_MAX_LEN] = {0};
90                 snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/.%s_for_subscribe", getuid(), CTSVC_IPC_SERVICE);
91                 __ipc = pims_ipc_create_for_subscribe(sock_file);
92                 if (!__ipc) {
93                         CTS_ERR("pims_ipc_create_for_subscribe error\n");
94                         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
95                         return CONTACTS_ERROR_IPC;
96                 }
97         }
98         __ipc_pubsub_ref++;
99         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
100         return CONTACTS_ERROR_NONE;
101 }
102
103 int ctsvc_ipc_destroy_for_change_subscription()
104 {
105         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
106
107         if (1 == __ipc_pubsub_ref) {
108                 pims_ipc_destroy_for_subscribe(__ipc);
109                 __ipc = NULL;
110         }
111         else if (1 < __ipc_pubsub_ref) {
112                 CTS_DBG("ctsvc pubsub ipc ref count : %d", __ipc_pubsub_ref);
113         }
114         else {
115                 CTS_DBG("System : please call connection APIs, connection count is (%d)", __ipc_pubsub_ref);
116                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
117                 return CONTACTS_ERROR_INVALID_PARAMETER;
118         }
119
120         __ipc_pubsub_ref--;
121
122         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
123         return CONTACTS_ERROR_NONE;
124 }
125
126 API int contacts_db_add_changed_cb_with_info(const char* view_uri,
127                 contacts_db_change_cb_with_info cb, void* user_data)
128 {
129         GSList *it = NULL;
130         subscribe_info_s *info = NULL;
131         db_callback_info_s *cb_info;
132         bool result = false;
133         int ret;
134
135         RETVM_IF(view_uri == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "view_uri is NULL");
136         RETVM_IF(cb == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "cb is NULL");
137
138         if (strncmp(view_uri, CTSVC_VIEW_URI_PHONELOG, strlen(CTSVC_VIEW_URI_PHONELOG)) == 0) {
139                 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_PHONELOG_READ, &result);
140                 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_ipc_client_check_permission fail (%d)", ret);
141                 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (phonelog read)");
142         }
143         else if (strncmp(view_uri, CTSVC_VIEW_URI_PERSON, strlen(CTSVC_VIEW_URI_PERSON)) == 0) {
144                 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_READ, &result);
145                 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_ipc_client_check_permission fail (%d)", ret);
146                 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (contact read)");
147         }
148         else {
149                 CTS_ERR("We support this API for only %s and %s", CTSVC_VIEW_URI_PERSON, CTSVC_VIEW_URI_PHONELOG);
150                 return CONTACTS_ERROR_INVALID_PARAMETER;
151         }
152
153         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
154
155         for (it=__db_change_subscribe_list;it;it=it->next) {
156                 if (!it->data) continue;
157
158                 info = it->data;
159                 if (STRING_EQUAL == strcmp(info->view_uri, view_uri))
160                         break;
161                 else
162                         info = NULL;
163         }
164
165         if (!info) {
166                 info = calloc(1, sizeof(subscribe_info_s));
167                 if (NULL == info) {
168                         CTS_ERR("calloc() Fail");
169                         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
170                         return CONTACTS_ERROR_OUT_OF_MEMORY;
171                 }
172
173                 if (pims_ipc_subscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, (char*)view_uri,
174                                         __ctsvc_db_subscriber_callback, (void*)info) != 0) {
175                         CTS_ERR("pims_ipc_subscribe error\n");
176                         free(info);
177                         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
178                         return CONTACTS_ERROR_IPC;
179                 }
180                 info->view_uri = strdup(view_uri);
181                 __db_change_subscribe_list = g_slist_append(__db_change_subscribe_list, info);
182         }
183         else {
184                 GSList *l;
185                 for (l = info->callbacks;l;l=l->next) {
186                         db_callback_info_s *cb_info = l->data;
187                         if (cb_info->cb == cb && cb_info->user_data == user_data) {
188                                 CTS_ERR("The same callback(%s) is already exist", view_uri);
189                                 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
190                                 return CONTACTS_ERROR_INVALID_PARAMETER;
191                         }
192                 }
193         }
194
195         cb_info = calloc(1, sizeof(db_callback_info_s));
196         cb_info->user_data = user_data;
197         cb_info->cb = cb;
198         info->callbacks = g_slist_append(info->callbacks, cb_info);
199
200         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
201         return CONTACTS_ERROR_NONE;
202 }
203
204 API int contacts_db_remove_changed_cb_with_info(const char* view_uri,
205                 contacts_db_change_cb_with_info cb, void* user_data)
206 {
207         GSList *it = NULL;
208         subscribe_info_s *info = NULL;
209
210         RETVM_IF(view_uri == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "view_uri is NULL");
211         RETVM_IF(cb == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "cb is NULL");
212
213         if (STRING_EQUAL != strcmp(view_uri, CTSVC_VIEW_URI_PHONELOG) &&
214                         STRING_EQUAL != strcmp(view_uri, CTSVC_VIEW_URI_PERSON)) {
215                 CTS_ERR("We support this API for only %s and %s", CTSVC_VIEW_URI_PERSON, CTSVC_VIEW_URI_PHONELOG);
216                 return CONTACTS_ERROR_INVALID_PARAMETER;
217         }
218
219         ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
220
221         for (it=__db_change_subscribe_list;it;it=it->next) {
222                 if (!it->data) continue;
223
224                 info = it->data;
225                 if (STRING_EQUAL == strcmp(info->view_uri, view_uri))
226                         break;
227                 else
228                         info = NULL;
229         }
230
231         if (info) {
232                 GSList *l;
233                 for (l = info->callbacks;l;l=l->next) {
234                         db_callback_info_s *cb_info = l->data;
235                         if (cb == cb_info->cb && user_data == cb_info->user_data) {
236                                 info->callbacks = g_slist_remove(info->callbacks, cb_info);
237                                 free(cb_info);
238                                 break;
239                         }
240                 }
241                 if (g_slist_length(info->callbacks) == 0) {
242                         pims_ipc_unsubscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, info->view_uri);
243                         __db_change_subscribe_list = g_slist_remove(__db_change_subscribe_list, info);
244                         free(info->view_uri);
245                         free(info);
246                 }
247         }
248
249         ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
250         return CONTACTS_ERROR_NONE;
251 }