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 WARN("Contacts service connect(%d)", _ctsvc_connection );
97 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_pid());
98 if (ret != CONTACTS_ERROR_NONE) {
100 ERR("ctsvc_ipc_connect() Fail(%d)", ret);
101 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
106 base->connection_count++;
108 if (0 == _ctsvc_connection) {
109 ret = ctsvc_socket_init();
110 if (ret != CONTACTS_ERROR_NONE) {
111 /* LCOV_EXCL_START */
112 ERR("ctsvc_socket_init() Fail(%d)", ret);
113 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
118 ret = ctsvc_inotify_init();
119 if (ret != CONTACTS_ERROR_NONE) {
120 /* LCOV_EXCL_START */
121 ERR("ctsvc_inotify_init() Fail(%d)", ret);
122 ctsvc_socket_final();
123 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
127 ctsvc_view_uri_init();
129 DBG("Contacts service has been already connected(%d)", _ctsvc_connection + 1);
132 if (1 == base->connection_count)
133 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
136 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
138 return CONTACTS_ERROR_NONE;
141 int ctsvc_client_disconnect(contacts_h contact)
145 ctsvc_base_s *base = (ctsvc_base_s*)contact;
146 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
148 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
150 if (1 == base->connection_count) {
151 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_pid(), _ctsvc_connection);
152 if (ret != CONTACTS_ERROR_NONE) {
153 /* LCOV_EXCL_START */
154 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
155 ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
159 ctsvc_inotify_unsubscribe_ipc_ready();
161 base->connection_count--;
163 if (1 == _ctsvc_connection) {
164 ctsvc_ipc_destroy_for_change_subscription(true);
165 ctsvc_view_uri_deinit();
166 ctsvc_inotify_close();
167 ctsvc_socket_final();
169 } else if (1 < _ctsvc_connection) {
170 DBG("connection count is %d", _ctsvc_connection);
172 /* LCOV_EXCL_START */
173 DBG("call contacts_connect(), connection count is %d", _ctsvc_connection);
174 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
175 return CONTACTS_ERROR_DB;
181 if (0 == base->connection_count) {
182 INFO("connection_count is 0. remove handle");
183 ret = ctsvc_client_handle_remove(ctsvc_client_get_pid(), contact);
184 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
186 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
188 return CONTACTS_ERROR_NONE;
191 int ctsvc_client_connect_on_thread(contacts_h contact)
194 ctsvc_base_s *base = (ctsvc_base_s*)contact;
195 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
197 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
199 if (0 == base->connection_count) {
200 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_tid());
201 if (ret != CONTACTS_ERROR_NONE) {
202 /* LCOV_EXCL_START */
203 ERR("ctsvc_ipc_connect() Fail(%d)", ret);
204 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
209 base->connection_count++;
211 if (0 == _ctsvc_connection_on_thread) {
212 ret = ctsvc_socket_init();
213 if (ret != CONTACTS_ERROR_NONE) {
214 /* LCOV_EXCL_START */
215 ERR("ctsvc_socket_init() Fail(%d)", ret);
216 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
221 ret = ctsvc_inotify_init();
222 if (ret != CONTACTS_ERROR_NONE) {
223 /* LCOV_EXCL_START */
224 ERR("ctsvc_inotify_init() Fail(%d)", ret);
225 ctsvc_socket_final();
226 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
230 ctsvc_view_uri_init();
231 } else if (0 < _ctsvc_connection_on_thread) {
232 DBG("System : Contacts service has been already connected");
235 if (1 == base->connection_count)
236 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
238 _ctsvc_connection_on_thread++;
240 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
242 return CONTACTS_ERROR_NONE;
245 int ctsvc_client_disconnect_on_thread(contacts_h contact)
248 ctsvc_base_s *base = (ctsvc_base_s*)contact;
249 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
251 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
253 if (1 == base->connection_count) {
254 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_tid(),
255 _ctsvc_connection_on_thread);
256 if (ret != CONTACTS_ERROR_NONE) {
257 /* LCOV_EXCL_START */
258 ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
259 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
263 ctsvc_inotify_unsubscribe_ipc_ready();
265 base->connection_count--;
267 if (1 == _ctsvc_connection_on_thread) {
268 if (0 == _ctsvc_connection)
269 ctsvc_ipc_destroy_for_change_subscription(true);
270 ctsvc_view_uri_deinit();
271 ctsvc_inotify_close();
272 ctsvc_socket_final();
273 DBG("System : connection_on_thread was destroyed successfully");
274 } else if (1 < _ctsvc_connection_on_thread) {
275 DBG("connection count is %d", _ctsvc_connection_on_thread);
277 /* LCOV_EXCL_START */
278 DBG("call contacts_connect_on_thread(), connection count is %d",
279 _ctsvc_connection_on_thread);
280 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
281 return CONTACTS_ERROR_DB;
285 _ctsvc_connection_on_thread--;
287 if (0 == base->connection_count) {
288 INFO("connection_count is 0. remove handle");
289 ret = ctsvc_client_handle_remove(ctsvc_client_get_tid(), contact);
290 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
292 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
294 return CONTACTS_ERROR_NONE;