4 * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <pims-ipc-svc.h>
24 #include <pims-ipc-data.h>
27 #include "ctsvc_internal.h"
28 #include "ctsvc_ipc_define.h"
29 #include "ctsvc_ipc_marshal.h"
30 #include "ctsvc_mutex.h"
31 #include "ctsvc_client_ipc.h"
32 #include "ctsvc_client_setting.h"
33 #include "contacts_extension.h"
37 contacts_db_change_cb_with_info cb;
47 static int __ipc_pubsub_ref = 0;
48 static pims_ipc_h __ipc = NULL;
49 static GSList *__db_change_subscribe_list = NULL;
51 static void __ctsvc_db_subscriber_callback(pims_ipc_h ipc, pims_ipc_data_h data, void *user_data)
55 subscribe_info_s *info = user_data;
58 ret = ctsvc_ipc_unmarshal_string(data, &str);
59 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_ipc_unmarshal_string() Fail(%d)", ret);
63 CTS_ERR("There is no changed data");
69 for (l = info->callbacks;l;l=l->next) {
70 db_callback_info_s *cb_info = l->data;
72 cb_info->cb(info->view_uri, str, cb_info->user_data);
80 int __ctsvc_db_recover_for_change_subscription()
83 subscribe_info_s *info = NULL;
85 for (it=__db_change_subscribe_list;it;it=it->next) {
86 if (NULL == it->data) continue;
90 if (pims_ipc_subscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, info->view_uri,
91 __ctsvc_db_subscriber_callback, (void*)info) != 0) {
92 CTS_ERR("pims_ipc_subscribe() Fail");
93 return CONTACTS_ERROR_IPC;
98 return CONTACTS_ERROR_NONE;
102 /* This API should be called in CTS_MUTEX_PIMS_IPC_PUBSUB mutex */
103 pims_ipc_h ctsvc_ipc_get_handle_for_change_subsciption()
108 int ctsvc_ipc_create_for_change_subscription()
110 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
112 if (0 < __ipc_pubsub_ref) {
114 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
115 return CONTACTS_ERROR_NONE;
119 char sock_file[CTSVC_PATH_MAX_LEN] = {0};
120 snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/.%s_for_subscribe", getuid(), CTSVC_IPC_SERVICE);
121 __ipc = pims_ipc_create_for_subscribe(sock_file);
123 CTS_ERR("pims_ipc_create_for_subscribe() Fail");
124 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
125 return CONTACTS_ERROR_IPC;
129 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
130 return CONTACTS_ERROR_NONE;
133 int ctsvc_ipc_recover_for_change_subscription()
136 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
137 if (__ipc_pubsub_ref <= 0) {
138 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
139 return CONTACTS_ERROR_NONE;
142 pims_ipc_destroy_for_subscribe(__ipc);
143 __ipc = pims_ipc_create_for_subscribe(CTSVC_IPC_SOCKET_PATH_FOR_CHANGE_SUBSCRIPTION);
145 CTS_ERR("pims_ipc_create_for_subscribe() Fail");
146 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
147 return CONTACTS_ERROR_IPC;
149 ret = ctsvc_setting_recover_for_change_subscription();
150 if (CONTACTS_ERROR_NONE != ret) {
151 CTS_ERR("ctsvc_setting_recover_for_change_subscription() Fail(%d)", ret);
152 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
155 ret = __ctsvc_db_recover_for_change_subscription();
156 if (CONTACTS_ERROR_NONE != ret) {
157 CTS_ERR("__ctsvc_db_recover_changed_cb_with_info() Fail(%d)", ret);
158 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
162 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
163 return CONTACTS_ERROR_NONE;
166 int ctsvc_ipc_destroy_for_change_subscription()
168 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
170 if (1 == __ipc_pubsub_ref) {
171 pims_ipc_destroy_for_subscribe(__ipc);
174 else if (1 < __ipc_pubsub_ref) {
175 CTS_DBG("ctsvc pubsub ipc ref count : %d", __ipc_pubsub_ref);
178 CTS_DBG("System : please call connection APIs, connection count is (%d)", __ipc_pubsub_ref);
179 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
180 return CONTACTS_ERROR_INVALID_PARAMETER;
185 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
186 return CONTACTS_ERROR_NONE;
189 API int contacts_db_add_changed_cb_with_info(const char* view_uri,
190 contacts_db_change_cb_with_info cb, void* user_data)
193 subscribe_info_s *info = NULL;
194 db_callback_info_s *cb_info;
198 RETVM_IF(view_uri == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "view_uri is NULL");
199 RETVM_IF(cb == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "cb is NULL");
201 if (STRING_EQUAL == strncmp(view_uri, CTSVC_VIEW_URI_PHONELOG, strlen(CTSVC_VIEW_URI_PHONELOG))) {
202 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_PHONELOG_READ, &result);
203 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_ipc_client_check_permission() Fail(%d)", ret);
204 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (phonelog read)");
206 else if (STRING_EQUAL == strncmp(view_uri, CTSVC_VIEW_URI_PERSON, strlen(CTSVC_VIEW_URI_PERSON))) {
207 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_READ, &result);
208 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_ipc_client_check_permission() Fail(%d)", ret);
209 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (contact read)");
212 CTS_ERR("We support this API for only %s and %s", CTSVC_VIEW_URI_PERSON, CTSVC_VIEW_URI_PHONELOG);
213 return CONTACTS_ERROR_INVALID_PARAMETER;
216 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
218 for (it=__db_change_subscribe_list;it;it=it->next) {
219 if (NULL == it->data) continue;
222 if (STRING_EQUAL == strcmp(info->view_uri, view_uri))
229 info = calloc(1, sizeof(subscribe_info_s));
231 CTS_ERR("calloc() Fail");
232 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
233 return CONTACTS_ERROR_OUT_OF_MEMORY;
236 if (pims_ipc_subscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, (char*)view_uri,
237 __ctsvc_db_subscriber_callback, (void*)info) != 0) {
238 CTS_ERR("pims_ipc_subscribe() Fail");
240 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
241 return CONTACTS_ERROR_IPC;
243 info->view_uri = strdup(view_uri);
244 __db_change_subscribe_list = g_slist_append(__db_change_subscribe_list, info);
248 for (l = info->callbacks;l;l=l->next) {
249 db_callback_info_s *cb_info = l->data;
250 if (cb_info->cb == cb && cb_info->user_data == user_data) {
251 CTS_ERR("The same callback(%s) is already exist", view_uri);
252 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
253 return CONTACTS_ERROR_INVALID_PARAMETER;
258 cb_info = calloc(1, sizeof(db_callback_info_s));
259 if (NULL == cb_info) {
260 CTS_ERR("calloc() Fail");
261 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
262 return CONTACTS_ERROR_OUT_OF_MEMORY;
264 cb_info->user_data = user_data;
266 info->callbacks = g_slist_append(info->callbacks, cb_info);
268 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
269 return CONTACTS_ERROR_NONE;
272 API int contacts_db_remove_changed_cb_with_info(const char* view_uri,
273 contacts_db_change_cb_with_info cb, void* user_data)
276 subscribe_info_s *info = NULL;
278 RETVM_IF(view_uri == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "view_uri is NULL");
279 RETVM_IF(cb == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "cb is NULL");
281 if (STRING_EQUAL != strcmp(view_uri, CTSVC_VIEW_URI_PHONELOG) &&
282 STRING_EQUAL != strcmp(view_uri, CTSVC_VIEW_URI_PERSON)) {
283 CTS_ERR("We support this API for only %s and %s", CTSVC_VIEW_URI_PERSON, CTSVC_VIEW_URI_PHONELOG);
284 return CONTACTS_ERROR_INVALID_PARAMETER;
287 ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB);
289 for (it=__db_change_subscribe_list;it;it=it->next) {
290 if (NULL == it->data) continue;
293 if (STRING_EQUAL == strcmp(info->view_uri, view_uri))
301 for (l = info->callbacks;l;l=l->next) {
302 db_callback_info_s *cb_info = l->data;
303 if (cb == cb_info->cb && user_data == cb_info->user_data) {
304 info->callbacks = g_slist_remove(info->callbacks, cb_info);
309 if (g_slist_length(info->callbacks) == 0) {
310 pims_ipc_unsubscribe(__ipc, CTSVC_IPC_SUBSCRIBE_MODULE, info->view_uri);
311 __db_change_subscribe_list = g_slist_remove(__db_change_subscribe_list, info);
312 free(info->view_uri);
317 ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
318 return CONTACTS_ERROR_NONE;