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;
75 static void _ctsvc_ipc_initialized_cb(void *user_data)
78 if (true == ctsvc_ipc_get_disconnected()) {
79 ctsvc_ipc_set_disconnected(false);
81 ctsvc_ipc_recover_for_change_subscription();
85 int ctsvc_client_connect(contacts_h contact)
89 ctsvc_base_s *base = (ctsvc_base_s*)contact;
90 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
92 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
93 if (0 == base->connection_count) {
94 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_pid());
95 if (ret != CONTACTS_ERROR_NONE) {
96 ERR("ctsvc_ipc_connect() Fail(%d)", ret);
97 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
101 base->connection_count++;
103 if (0 == _ctsvc_connection) {
104 ret = ctsvc_socket_init();
105 if (ret != CONTACTS_ERROR_NONE) {
106 ERR("ctsvc_socket_init() Fail(%d)", ret);
107 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
111 ret = ctsvc_inotify_init();
112 if (ret != CONTACTS_ERROR_NONE) {
113 ERR("ctsvc_inotify_init() Fail(%d)", ret);
114 ctsvc_socket_final();
115 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
118 ctsvc_view_uri_init();
120 DBG("Contacts service has been already connected(%d)", _ctsvc_connection + 1);
123 if (1 == base->connection_count)
124 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
127 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
129 return CONTACTS_ERROR_NONE;
132 int ctsvc_client_disconnect(contacts_h contact)
136 ctsvc_base_s *base = (ctsvc_base_s*)contact;
137 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
139 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
141 if (1 == base->connection_count) {
142 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_pid(), _ctsvc_connection);
143 if (ret != CONTACTS_ERROR_NONE) {
144 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
145 ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
148 ctsvc_inotify_unsubscribe_ipc_ready();
150 base->connection_count--;
152 if (1 == _ctsvc_connection) {
153 ctsvc_ipc_destroy_for_change_subscription(true);
154 ctsvc_view_uri_deinit();
155 ctsvc_inotify_close();
156 ctsvc_socket_final();
158 } else if (1 < _ctsvc_connection) {
159 DBG("connection count is %d", _ctsvc_connection);
161 DBG("call contacts_connect(), connection count is %d", _ctsvc_connection);
162 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
163 return CONTACTS_ERROR_DB;
168 if (0 == base->connection_count) {
169 INFO("connection_count is 0. remove handle");
170 ret = ctsvc_client_handle_remove(ctsvc_client_get_pid(), contact);
171 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
173 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
175 return CONTACTS_ERROR_NONE;
178 int ctsvc_client_connect_on_thread(contacts_h contact)
181 ctsvc_base_s *base = (ctsvc_base_s*)contact;
182 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
184 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
186 if (0 == base->connection_count) {
187 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_tid());
188 if (ret != CONTACTS_ERROR_NONE) {
189 ERR("ctsvc_ipc_connect() Fail(%d)", ret);
190 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
194 base->connection_count++;
196 if (0 == _ctsvc_connection_on_thread) {
197 ret = ctsvc_socket_init();
198 if (ret != CONTACTS_ERROR_NONE) {
199 ERR("ctsvc_socket_init() Fail(%d)", ret);
200 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
204 ret = ctsvc_inotify_init();
205 if (ret != CONTACTS_ERROR_NONE) {
206 ERR("ctsvc_inotify_init() Fail(%d)", ret);
207 ctsvc_socket_final();
208 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
211 ctsvc_view_uri_init();
212 } else if (0 < _ctsvc_connection_on_thread) {
213 DBG("System : Contacts service has been already connected");
216 if (1 == base->connection_count)
217 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
219 _ctsvc_connection_on_thread++;
221 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
223 return CONTACTS_ERROR_NONE;
226 int ctsvc_client_disconnect_on_thread(contacts_h contact)
229 ctsvc_base_s *base = (ctsvc_base_s*)contact;
230 RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
232 ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
234 if (1 == base->connection_count) {
235 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_tid(),
236 _ctsvc_connection_on_thread);
237 if (ret != CONTACTS_ERROR_NONE) {
238 ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
239 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
242 ctsvc_inotify_unsubscribe_ipc_ready();
244 base->connection_count--;
246 if (1 == _ctsvc_connection_on_thread) {
247 if (0 == _ctsvc_connection)
248 ctsvc_ipc_destroy_for_change_subscription(true);
249 ctsvc_view_uri_deinit();
250 ctsvc_inotify_close();
251 ctsvc_socket_final();
252 DBG("System : connection_on_thread was destroyed successfully");
253 } else if (1 < _ctsvc_connection_on_thread) {
254 DBG("connection count is %d", _ctsvc_connection_on_thread);
256 DBG("call contacts_connect_on_thread(), connection count is %d",
257 _ctsvc_connection_on_thread);
258 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
259 return CONTACTS_ERROR_DB;
262 _ctsvc_connection_on_thread--;
264 if (0 == base->connection_count) {
265 INFO("connection_count is 0. remove handle");
266 ret = ctsvc_client_handle_remove(ctsvc_client_get_tid(), contact);
267 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
269 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
271 return CONTACTS_ERROR_NONE;