4 * Copyright (c) 2010 - 2015 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.
20 #include <sys/socket.h>
25 #include "ctsvc_internal.h"
26 #include "ctsvc_socket.h"
27 #include "ctsvc_mutex.h"
28 #include "ctsvc_inotify.h"
29 #include "ctsvc_client_ipc.h"
30 #include "ctsvc_client_utils.h"
31 #include "ctsvc_client_handle.h"
32 #include "ctsvc_client_service_helper.h"
34 static int _ctsvc_connection = 0;
35 static __thread int _ctsvc_connection_on_thread = 0;
37 int ctsvc_client_get_thread_connection_count()
39 return _ctsvc_connection_on_thread;
42 int ctsvc_client_connect_with_flags(contacts_h contact, unsigned int flags)
45 int ret = CONTACTS_ERROR_NONE;
47 /* If new flag is defined, errer check should be updated */
48 RETVM_IF(flags & 0x11111110, CONTACTS_ERROR_INVALID_PARAMETER, "flags is invalid");
50 ret = ctsvc_client_connect(contact);
51 if (ret == CONTACTS_ERROR_PERMISSION_DENIED)
53 else if (ret == CONTACTS_ERROR_NONE)
56 if (flags & CONTACTS_CONNECT_FLAG_RETRY) {
58 int waiting_time = 500;
59 for (i = 0; i < 9; i++) {
60 usleep(waiting_time * 1000);
61 DBG("retry cnt=%d, ret=%x, %d", (i+1), ret, waiting_time);
62 ret = ctsvc_client_connect(contact);
63 if (ret == CONTACTS_ERROR_NONE)
66 waiting_time += 30000;
76 static void _ctsvc_ipc_initialized_cb(void *user_data)
79 if (true == ctsvc_ipc_get_disconnected()) {
80 ctsvc_ipc_set_disconnected(false);
82 ctsvc_ipc_recover_for_change_subscription();
87 int ctsvc_client_connect(contacts_h contact)
91 ctsvc_base_s *base = (ctsvc_base_s*)contact;
92 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
94 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
95 if (0 == base->connection_count) {
96 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_pid());
97 if (ret != CONTACTS_ERROR_NONE) {
99 ERR("ctsvc_ipc_connect() Fail(%d)", ret);
100 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
105 base->connection_count++;
107 if (0 == _ctsvc_connection) {
108 ret = ctsvc_socket_init();
109 if (ret != CONTACTS_ERROR_NONE) {
110 /* LCOV_EXCL_START */
111 ERR("ctsvc_socket_init() Fail(%d)", ret);
112 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
117 ret = ctsvc_inotify_init();
118 if (ret != CONTACTS_ERROR_NONE) {
119 /* LCOV_EXCL_START */
120 ERR("ctsvc_inotify_init() Fail(%d)", ret);
121 ctsvc_socket_final();
122 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
126 ctsvc_view_uri_init();
128 DBG("Contacts service has been already connected(%d)", _ctsvc_connection + 1);
131 if (1 == base->connection_count)
132 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
135 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
137 return CONTACTS_ERROR_NONE;
140 int ctsvc_client_disconnect(contacts_h contact)
144 ctsvc_base_s *base = (ctsvc_base_s*)contact;
145 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
147 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
149 if (1 == base->connection_count) {
150 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_pid(), _ctsvc_connection);
151 if (ret != CONTACTS_ERROR_NONE) {
152 /* LCOV_EXCL_START */
153 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
154 ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
158 ctsvc_inotify_unsubscribe_ipc_ready();
160 base->connection_count--;
162 if (1 == _ctsvc_connection) {
163 ctsvc_ipc_destroy_for_change_subscription(true);
164 ctsvc_view_uri_deinit();
165 ctsvc_inotify_close();
166 ctsvc_socket_final();
168 } else if (1 < _ctsvc_connection) {
169 DBG("connection count is %d", _ctsvc_connection);
171 /* LCOV_EXCL_START */
172 DBG("call contacts_connect(), connection count is %d", _ctsvc_connection);
173 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
174 return CONTACTS_ERROR_DB;
180 if (0 == base->connection_count) {
181 INFO("connection_count is 0. remove handle");
182 ret = ctsvc_client_handle_remove(ctsvc_client_get_pid(), contact);
183 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
185 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
187 return CONTACTS_ERROR_NONE;
190 int ctsvc_client_connect_on_thread(contacts_h contact)
193 ctsvc_base_s *base = (ctsvc_base_s*)contact;
194 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
196 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
198 if (0 == base->connection_count) {
199 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_tid());
200 if (ret != CONTACTS_ERROR_NONE) {
201 /* LCOV_EXCL_START */
202 ERR("ctsvc_ipc_connect() Fail(%d)", ret);
203 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
208 base->connection_count++;
210 if (0 == _ctsvc_connection_on_thread) {
211 ret = ctsvc_socket_init();
212 if (ret != CONTACTS_ERROR_NONE) {
213 /* LCOV_EXCL_START */
214 ERR("ctsvc_socket_init() Fail(%d)", ret);
215 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
220 ret = ctsvc_inotify_init();
221 if (ret != CONTACTS_ERROR_NONE) {
222 /* LCOV_EXCL_START */
223 ERR("ctsvc_inotify_init() Fail(%d)", ret);
224 ctsvc_socket_final();
225 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
229 ctsvc_view_uri_init();
230 } else if (0 < _ctsvc_connection_on_thread) {
231 DBG("System : Contacts service has been already connected");
234 if (1 == base->connection_count)
235 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
237 _ctsvc_connection_on_thread++;
239 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
241 return CONTACTS_ERROR_NONE;
244 int ctsvc_client_disconnect_on_thread(contacts_h contact)
247 ctsvc_base_s *base = (ctsvc_base_s*)contact;
248 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
250 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
252 if (1 == base->connection_count) {
253 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_tid(),
254 _ctsvc_connection_on_thread);
255 if (ret != CONTACTS_ERROR_NONE) {
256 /* LCOV_EXCL_START */
257 ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
258 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
262 ctsvc_inotify_unsubscribe_ipc_ready();
264 base->connection_count--;
266 if (1 == _ctsvc_connection_on_thread) {
267 if (0 == _ctsvc_connection)
268 ctsvc_ipc_destroy_for_change_subscription(true);
269 ctsvc_view_uri_deinit();
270 ctsvc_inotify_close();
271 ctsvc_socket_final();
272 DBG("System : connection_on_thread was destroyed successfully");
273 } else if (1 < _ctsvc_connection_on_thread) {
274 DBG("connection count is %d", _ctsvc_connection_on_thread);
276 /* LCOV_EXCL_START */
277 DBG("call contacts_connect_on_thread(), connection count is %d",
278 _ctsvc_connection_on_thread);
279 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
280 return CONTACTS_ERROR_DB;
284 _ctsvc_connection_on_thread--;
286 if (0 == base->connection_count) {
287 INFO("connection_count is 0. remove handle");
288 ret = ctsvc_client_handle_remove(ctsvc_client_get_tid(), contact);
289 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
291 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
293 return CONTACTS_ERROR_NONE;