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 #ifdef _CONTACTS_IPC_CLIENT
30 #include "ctsvc_client_utils.h"
32 static int __ctsvc_conn_refcnt = 0;
33 static int __ctsvc_sockfd = -1;
35 int ctsvc_socket_init(void)
38 struct sockaddr_un caddr;
42 WARN("ctsvc_socket_init: socket ref count : %d", __ctsvc_conn_refcnt);
43 if (0 < __ctsvc_conn_refcnt) {
45 __ctsvc_conn_refcnt++;
46 return CONTACTS_ERROR_NONE;
50 char sock_file[CTSVC_PATH_MAX_LEN] = {0};
52 #ifdef _CONTACTS_IPC_CLIENT
53 if (ctsvc_client_is_in_system_session()) {
55 if (CONTACTS_ERROR_NONE != ctsvc_client_get_active_uid(&uid))
56 return CONTACTS_ERROR_SYSTEM;
61 wrn = snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/%s", uid, CTSVC_SOCKET_FILE);
63 WARN("Error writing in sock file (%s)", sock_file); /* LCOV_EXCL_LINE */
66 bzero(&caddr, sizeof(caddr));
67 caddr.sun_family = AF_UNIX;
68 wrn = snprintf(caddr.sun_path, sizeof(caddr.sun_path), "%s", sock_file);
70 WARN("Error writing in unix socket path (%s)", caddr.sun_path); /* LCOV_EXCL_LINE */
72 __ctsvc_sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
73 RETVM_IF(-1 == __ctsvc_sockfd, CONTACTS_ERROR_IPC, /* LCOV_EXCL_LINE */
74 "socket() Fail(errno = %d)", errno); /* LCOV_EXCL_LINE */
76 ret = connect(__ctsvc_sockfd, (struct sockaddr *)&caddr, sizeof(caddr));
79 ERR("connect() Fail(errno = %d)", errno);
80 close(__ctsvc_sockfd);
82 return CONTACTS_ERROR_IPC;
86 __ctsvc_conn_refcnt++;
87 return CONTACTS_ERROR_NONE;
90 void ctsvc_socket_final(void)
92 if (1 < __ctsvc_conn_refcnt) {
94 DBG("socket ref count : %d", __ctsvc_conn_refcnt);
95 __ctsvc_conn_refcnt--;
98 } else if (__ctsvc_conn_refcnt < 1) {
99 DBG("Please call connection API. socket ref count : %d", __ctsvc_conn_refcnt);
102 __ctsvc_conn_refcnt--;
104 close(__ctsvc_sockfd);
107 /* LCOV_EXCL_START */
108 static inline int __ctsvc_safe_write(int fd, const char *buf, int buf_size)
112 ret = write(fd, buf+writed, buf_size);
125 static inline int __ctsvc_safe_read(int fd, char *buf, int buf_size)
127 int ret, read_size = 0;
129 ret = read(fd, buf+read_size, buf_size);
142 static int __ctsvc_socket_handle_return(int fd, ctsvc_socket_msg_s *msg)
147 ret = __ctsvc_safe_read(fd, (char *)msg, sizeof(ctsvc_socket_msg_s));
148 RETVM_IF(-1 == ret, CONTACTS_ERROR_IPC, "__ctsvc_safe_read() Fail(errno = %d)", errno);
150 WARN_IF(CTSVC_SOCKET_MSG_TYPE_REQUEST_RETURN_VALUE != msg->type,
151 "Unknown Type(%d), ret=%d, attach_num= %d,"
152 "attach1 = %d, attach2 = %d, attach3 = %d, attach4 = %d",
153 msg->type, msg->val, msg->attach_num,
154 msg->attach_sizes[0], msg->attach_sizes[1], msg->attach_sizes[2],
155 msg->attach_sizes[3]);
157 RETVM_IF(CTSVC_SOCKET_MSG_REQUEST_MAX_ATTACH < msg->attach_num, CONTACTS_ERROR_IPC,
158 "Invalid msg(attach_num = %d)", msg->attach_num);
160 return CONTACTS_ERROR_NONE;
163 static int __ctsvc_cancel_sim_import(int fd)
166 ctsvc_socket_msg_s msg = {0};
168 RETVM_IF(-1 == fd, CONTACTS_ERROR_IPC, "socket is not connected");
170 msg.type = CTSVC_SOCKET_MSG_TYPE_CANCEL_IMPORT_SIM;
172 ret = __ctsvc_safe_write(fd, (char *)&msg, sizeof(msg));
173 RETVM_IF(-1 == ret, CONTACTS_ERROR_IPC, "__ctsvc_safe_write() Fail(errno = %d)", errno);
175 return CONTACTS_ERROR_NONE;
178 static int __ctsvc_client_socket_response_handler(int fd, ctsvc_socket_msg_s *msg, contacts_sim_import_progress_cb callback, void *user_data)
184 ret = __ctsvc_safe_read(fd, (char *)msg, sizeof(ctsvc_socket_msg_s));
185 RETVM_IF(-1 == ret, CONTACTS_ERROR_IPC, "__ctsvc_safe_read() Fail(errno = %d)", errno);
186 RETVM_IF(CTSVC_SOCKET_MSG_REQUEST_MAX_ATTACH < msg->attach_num, CONTACTS_ERROR_IPC,
187 "Invalid msg(attach_num = %d)", msg->attach_num);
190 case CTSVC_SOCKET_MSG_TYPE_REQUEST_RETURN_VALUE:
193 case CTSVC_SOCKET_MSG_TYPE_REQUEST_INVOKE_CB:
194 DBG("total[%d], index[%d]", msg->val, msg->data);
196 if (false == callback(msg->val, msg->data, user_data))
197 __ctsvc_cancel_sim_import(fd);
204 WARN("Unknown Type(%d), ret=%d, attach_num= %d,"
205 "attach1 = %d, attach2 = %d, attach3 = %d, attach4 = %d",
206 msg->type, msg->val, msg->attach_num,
207 msg->attach_sizes[0], msg->attach_sizes[1], msg->attach_sizes[2],
208 msg->attach_sizes[3]);
211 } while (CTSVC_SOCKET_MSG_TYPE_REQUEST_RETURN_VALUE != msg->type);
213 return CONTACTS_ERROR_NONE;
216 static void __ctsvc_remove_invalid_msg(int fd, int size)
219 char dummy[CTSVC_SOCKET_MSG_SIZE] = {0};
222 if (sizeof(dummy) < size) {
224 ret = read(fd, dummy, sizeof(dummy));
233 ret = read(fd, dummy, size);
244 int ctsvc_request_sim_import(int sim_slot_no, contacts_sim_import_progress_cb callback,
248 ctsvc_socket_msg_s msg = {0};
251 RETVM_IF(-1 == __ctsvc_sockfd, CONTACTS_ERROR_IPC, "socket is not connected");
253 msg.type = CTSVC_SOCKET_MSG_TYPE_REQUEST_IMPORT_SIM;
255 snprintf(src, sizeof(src), "%d", sim_slot_no);
257 msg.attach_sizes[0] = strlen(src);
259 ret = __ctsvc_safe_write(__ctsvc_sockfd, (char *)&msg, sizeof(msg));
260 RETVM_IF(-1 == ret, CONTACTS_ERROR_IPC, "__ctsvc_safe_write() Fail(errno = %d)", errno);
262 ret = __ctsvc_safe_write(__ctsvc_sockfd, src, msg.attach_sizes[0]);
263 RETVM_IF(-1 == ret, CONTACTS_ERROR_IPC, "__ctsvc_safe_write() Fail(errno = %d)", errno);
265 ret = __ctsvc_client_socket_response_handler(__ctsvc_sockfd, &msg, callback, user_data);
266 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "__ctsvc_socket_handle_return() Fail(%d)", ret);
267 DBG("attach_num = %d", msg.attach_num);
269 for (i = 0; i < msg.attach_num; i++)
270 __ctsvc_remove_invalid_msg(__ctsvc_sockfd, msg.attach_sizes[i]);
275 int ctsvc_request_sim_get_initialization_status(int sim_slot_no, bool *completed)
278 ctsvc_socket_msg_s msg = {0};
279 char dest[CTSVC_SOCKET_MSG_SIZE] = {0};
282 RETVM_IF(-1 == __ctsvc_sockfd, CONTACTS_ERROR_IPC, "socket is not connected");
284 msg.type = CTSVC_SOCKET_MSG_TYPE_REQUEST_SIM_INIT_COMPLETE;
286 snprintf(src, sizeof(src), "%d", sim_slot_no);
288 msg.attach_sizes[0] = strlen(src);
290 ret = __ctsvc_safe_write(__ctsvc_sockfd, (char *)&msg, sizeof(msg));
291 RETVM_IF(-1 == ret, CONTACTS_ERROR_IPC, "__ctsvc_safe_write() Fail(errno = %d)", errno);
293 ret = __ctsvc_safe_write(__ctsvc_sockfd, src, msg.attach_sizes[0]);
294 RETVM_IF(-1 == ret, CONTACTS_ERROR_IPC, "__ctsvc_safe_write() Fail(errno = %d)", errno);
296 ret = __ctsvc_socket_handle_return(__ctsvc_sockfd, &msg);
297 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "__ctsvc_socket_handle_return() Fail(%d)", ret);
298 DBG("attach_num = %d", msg.attach_num);
300 ret = __ctsvc_safe_read(__ctsvc_sockfd, dest, msg.attach_sizes[0]);
301 RETVM_IF(-1 == ret, CONTACTS_ERROR_IPC, "__ctsvc_safe_read() Fail(errno = %d)", errno);
308 INFO("sim init complete : %d", *completed);