4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: YoungHun Kim <yh8004.kim@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include "muse_client.h"
23 #include "muse_core_internal.h"
28 #define LOG_TAG "MUSED_CLIENT"
30 static GMutex mc_mutex;
31 static GHashTable *mc_table;
32 static int mc_table_id;
34 static const char *UDS_files[MUSE_CHANNEL_MAX] = {MUSE_MSG_SOCK, MUSE_DATA_SOCK};
36 #ifdef MUSE_USE_CLIENT_SIGHANDLER
38 static struct sigaction mc_int_old_action;
39 static struct sigaction mc_abrt_old_action;
40 static struct sigaction mc_segv_old_action;
41 static struct sigaction mc_term_old_action;
42 static struct sigaction mc_sys_old_action;
44 static gboolean _mc_table_remove_func(gpointer key, gpointer value, gpointer user_data);
45 static void _mc_sigaction(int signo, siginfo_t *siginfo, void *context);
46 static void _mc_constructor(void) __attribute__((constructor));
49 static int _mc_new(muse_channel_e channel);
50 static void _mc_table_new(void);
51 static gpointer _mc_get_fd_ptr(int sock_fd);
53 static int _muse_client_new(muse_channel_e channel);
55 #ifdef MUSE_USE_CLIENT_SIGHANDLER
56 static gboolean _mc_table_remove_func(gpointer key, gpointer value, gpointer user_data)
58 int sock_fd = GPOINTER_TO_INT(key);
60 LOGW("close muse connection fd %d", sock_fd);
62 muse_core_connection_close(sock_fd);
67 static void _mc_sigaction(int signo, siginfo_t *siginfo, void *context)
69 struct sigaction *old_action = NULL;
70 pid_t my_pid = getpid();
72 LOGE("Enter - signo [%d], pid [%d]", signo, my_pid);
74 /* close all opened fds */
75 g_mutex_lock(&mc_mutex);
78 g_hash_table_foreach_remove(mc_table, _mc_table_remove_func, NULL);
80 g_mutex_unlock(&mc_mutex);
82 /* call old signal handler */
85 old_action = &mc_int_old_action;
88 old_action = &mc_abrt_old_action;
91 old_action = &mc_segv_old_action;
94 old_action = &mc_term_old_action;
97 old_action = &mc_sys_old_action;
100 LOGE("unhandled signal %d", signo);
104 if (old_action->sa_sigaction)
105 old_action->sa_sigaction(signo, siginfo, context);
107 sigaction(signo, old_action, NULL);
116 static void _mc_constructor(void)
118 struct sigaction mc_action;
119 mc_action.sa_sigaction = _mc_sigaction;
120 mc_action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
124 sigemptyset(&mc_action.sa_mask);
126 sigaction(SIGINT, &mc_action, &mc_int_old_action);
127 sigaction(SIGABRT, &mc_action, &mc_abrt_old_action);
128 sigaction(SIGSEGV, &mc_action, &mc_segv_old_action);
129 sigaction(SIGTERM, &mc_action, &mc_term_old_action);
130 sigaction(SIGSYS, &mc_action, &mc_sys_old_action);
138 static int _mc_new(muse_channel_e channel)
140 struct sockaddr_un address;
141 int len, ret = MUSE_ERR;
143 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
146 muse_return_val_if_fail(channel < MUSE_CHANNEL_MAX, MM_ERROR_INVALID_ARGUMENT);
149 sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
150 if (!muse_core_fd_is_valid(sock_fd)) {
151 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
152 LOGE("[socket failure] %d socket %s", errno, err_msg);
153 muse_core_dump_fd_state(sock_fd);
156 LOGI("sockfd: %d", sock_fd);
158 if (fcntl(sock_fd, F_SETFD, FD_CLOEXEC) < 0) {
159 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
160 LOGE("unable to set on ctrl socket fd %d: %s", sock_fd, err_msg);
166 memset(&address, 0, sizeof(address));
167 address.sun_family = AF_UNIX;
168 strncpy(address.sun_path, UDS_files[channel], sizeof(address.sun_path) - 1);
169 len = sizeof(address);
171 if (muse_core_set_nonblocking(sock_fd, false) != MM_ERROR_NONE)
172 LOGE("Error - fd (%d) set blocking", sock_fd);
174 if ((ret = connect(sock_fd, (struct sockaddr *)&address, len)) < 0) {
175 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
176 LOGE("[Critical Error : %d] connect failure : %s", errno, err_msg);
181 LOGI("[%d] #%d guaranteed that connect was returned", sock_fd, mc_table_id);
182 g_mutex_lock(&mc_mutex);
183 g_hash_table_insert(mc_table, GINT_TO_POINTER(sock_fd), GINT_TO_POINTER(mc_table_id++));
184 g_mutex_unlock(&mc_mutex);
190 static void _mc_table_new(void)
192 g_mutex_lock(&mc_mutex);
196 mc_table = g_hash_table_new(g_direct_hash, g_direct_equal);
197 LOGD("client table : %p", mc_table);
200 g_mutex_unlock(&mc_mutex);
202 muse_core_create_fd_table();
205 static gpointer _mc_get_fd_ptr(int sock_fd)
207 muse_return_val_if_fail(mc_table, NULL);
209 return g_hash_table_lookup(mc_table, GINT_TO_POINTER(sock_fd));
212 static int _muse_client_new(muse_channel_e channel)
214 if (!muse_server_is_ready()) {
215 LOGE("muse server is not ready");
216 return MM_ERROR_UNKNOWN;
219 if (channel == MUSE_CHANNEL_MSG)
222 return _mc_new(channel);
225 int muse_client_new(void)
227 return _muse_client_new(MUSE_CHANNEL_MSG);
230 int muse_client_new_data_ch(void)
232 return _muse_client_new(MUSE_CHANNEL_DATA);
235 int muse_client_close(int sock_fd)
237 int ret = MM_ERROR_NONE;
239 ret = muse_core_connection_close(sock_fd);
240 if (ret != MM_ERROR_NONE) {
241 LOGE("close connection failed 0x%x", ret);
245 /* remove fd from table */
246 g_mutex_lock(&mc_mutex);
248 if (g_hash_table_remove(mc_table, GINT_TO_POINTER(sock_fd)))
249 LOGD("success : remove fd %d from table", sock_fd);
251 LOGW("fail : remove fd %d from table[%p]", sock_fd, mc_table);
253 g_mutex_unlock(&mc_mutex);
255 #ifdef MUSE_GCOV_TEST
256 muse_core_gcov_flush();
259 return MM_ERROR_NONE;
262 int muse_client_ipc_push_data(int sock_fd, const char *data, int size, uint64_t data_id)
264 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
265 muse_recv_data_head_t header;
268 muse_return_val_if_fail(data, MM_ERROR_INVALID_ARGUMENT);
269 muse_return_val_if_fail(muse_core_fd_is_valid(sock_fd), MM_ERROR_INVALID_ARGUMENT);
271 header.marker = MUSE_DATA_HEAD;
275 LOGD("[%d] header.marker : %x header.size : %d header.id : %"G_GUINT64_FORMAT"",
276 sock_fd, header.marker, header.size, header.id);
278 if ((sended_len = send(sock_fd, &header, sizeof(muse_recv_data_head_t), 0)) < 0) {
279 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
280 LOGE("[%d] fail to send msg (%s) %d", sock_fd, err_msg, errno);
283 if ((sended_len += send(sock_fd, data, size, 0)) < 0) {
284 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
285 LOGE("[%d] fail to send msg (%s) %d", sock_fd, err_msg, errno);
291 int muse_client_get_fd_id_value(int sock_fd)
293 gpointer sock_id_ptr = _mc_get_fd_ptr(sock_fd);
295 muse_return_val_if_fail(sock_id_ptr, MUSE_ERR);
297 return GPOINTER_TO_INT(sock_id_ptr);
300 bool muse_client_check_fd_id_value(int sock_fd, int sock_id)
302 gpointer sock_id_ptr = _mc_get_fd_ptr(sock_fd);
304 muse_return_val_if_fail(sock_id_ptr, false);
306 if (sock_id == GPOINTER_TO_INT(sock_id_ptr))
312 int muse_client_get_module_index(const char *module_name, int *module_index)
319 bool module_name_matched = false;
322 muse_return_val_if_fail(module_name, MM_ERROR_INVALID_ARGUMENT);
323 muse_return_val_if_fail(module_index, MM_ERROR_INVALID_ARGUMENT);
327 mc_dict = iniparser_load(CONFFILE);
328 muse_return_val_if_fail(mc_dict, PARSE_ERROR);
330 str = (const char *)iniparser_getstring(mc_dict, MUSE_HOST, NULL);
332 LOGE("Error - iniparser_getstring (%s)", MUSE_HOST);
333 iniparser_freedict(mc_dict);
339 LOGE("Error - hosts allocation");
340 iniparser_freedict(mc_dict);
344 host = strtok_r(hosts, INI_PARSER_COMMA, &ptr);
348 if (strncmp(module_name, host, strlen(module_name) + 1) == 0) {
349 module_name_matched = true;
354 host = strtok_r(NULL, INI_PARSER_COMMA, &ptr);
360 iniparser_freedict(mc_dict);
362 if (module_name_matched) {
364 return MM_ERROR_NONE;
366 LOGE("You have to check if [%s] of [%s] is exact", module_name, CONFFILE);
367 *module_index = MUSE_ERR;
369 return MM_ERROR_INVALID_ARGUMENT;