Fix coverity issue
[platform/core/multimedia/mmsvc-core.git] / core / src / muse_core.c
1 /*
2  * muse-core
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: YoungHun Kim <yh8004.kim@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include "muse_core_internal.h"
23 #include <json.h>
24 #include <sys/mman.h>
25
26 #undef LOG_TAG
27 #define LOG_TAG                                                         "MUSED_CORE"
28
29 #define STR_TIME_FORMAT                                         "%m-%d %H:%M:%S"
30 #define MUSE_MIN_SEC_VALUE                                      60
31 #define MUSE_HOUR_MIN_VALUE                                     60
32 #define MUSE_DAY_HOUR_VALUE                                     24
33
34 #define MUSE_WATCHDOG_CHECK_PERIOD                      10
35 #define MUSE_WATCHDOG_CHECK_COUNT                       3
36 #define MUSE_WATCHDOG_TIMER_PERIOD                      5
37
38 static const char *msg_type[] = { "normal type", "fds type" };
39
40 static GMutex msg_lock;
41 static GMutex msg_ipc_lock;
42
43 static GMutex fd_state_lock;
44 static GHashTable *fd_state_table;
45
46 static int _muse_get_valid_fd_count(int *fds);
47 static void _muse_msg_json_set_error(muse_core_msg_parse_err_e *err, int jerr);
48 static json_object *_muse_msg_json_tokener_parse_len(const char *str, int *len, muse_core_msg_parse_err_e *err);
49 static gboolean _muse_msg_is_mem_ptr_valid(gpointer ptr);
50 static void _muse_msg_json_factory_args(json_object *jobj, va_list ap);
51 static json_object *_muse_msg_json_find_obj(json_object *jobj, const char *find_key);
52 static gboolean _muse_msg_json_get_obj_value(json_object *obj, muse_core_msg_type_e m_type, void *data);
53
54 #ifdef MUSE_GCOV_TEST
55 void muse_core_gcov_flush(void)
56 {
57         __gcov_flush();
58 }
59
60 void muse_core_setenv(const char *name, const char *value, int replace)
61 {
62         setenv(name, value, replace);
63 }
64
65 #endif
66
67 static int _muse_get_valid_fd_count(int *fds)
68 {
69         int idx;
70         for (idx = 0; idx < MUSE_NUM_FD; idx++) {
71                 if (fds[idx] == MUSE_ERR)
72                         break;
73         }
74         return idx;
75 }
76
77 static void _muse_msg_json_set_error(muse_core_msg_parse_err_e *err, int jerr)
78 {
79         if (err) {
80                 switch (jerr) {
81                 case json_tokener_success:
82                         *err = MUSE_MSG_PARSE_ERROR_NONE;
83                         break;
84                 case json_tokener_continue:
85                         *err = MUSE_MSG_PARSE_ERROR_CONTINUE;
86                         break;
87                 default:
88                         *err = MUSE_MSG_PARSE_ERROR_OTHER;
89                         break;
90                 }
91         }
92 }
93
94 static json_object *_muse_msg_json_tokener_parse_len(const char *str, int *len, muse_core_msg_parse_err_e *err)
95 {
96         struct json_tokener *tok = NULL;
97         struct json_object *obj = NULL;
98         int str_len = 0;
99
100         muse_return_val_if_fail(str, NULL);
101
102         tok = json_tokener_new();
103
104         if (!tok) {
105                 LOGE("tokener creation error");
106                 goto out;
107         }
108
109         str_len = strlen(str);
110         obj = json_tokener_parse_ex(tok, str, str_len);
111
112         if (!obj) {
113                 LOGE("parsing error : [length : %d] %s", str_len, str);
114                 goto out;
115         }
116
117         if (len)
118                 *len = tok->char_offset;
119
120         if (tok->err != json_tokener_success) {
121                 LOGE("Json Error(%d) : %s", tok->err, json_tokener_error_desc(tok->err));
122                 json_object_put(obj);
123                 obj = NULL;
124         }
125         _muse_msg_json_set_error(err, tok->err);
126
127 out:
128         if (tok)
129                 json_tokener_free(tok);
130
131         return obj;
132 }
133
134 static gboolean _muse_msg_is_mem_ptr_valid(gpointer ptr)
135 {
136         size_t page_size = sysconf(_SC_PAGESIZE);
137         gpointer base = (gpointer)((size_t)ptr / page_size * page_size);
138
139         return msync(base, page_size, MS_ASYNC) == 0;
140 }
141
142 static void _muse_msg_json_factory_args(json_object *jobj, va_list ap)
143 {
144         int type, len, idx;
145         char *name;
146         int *value;
147         json_object *jarr;
148
149         while ((type = va_arg(ap, int)) != 0) {
150                 name = va_arg(ap, char *);
151                 switch (type) {
152                 case MUSE_TYPE_INT:
153                         json_object_object_add(jobj, name, json_object_new_int(va_arg(ap, int32_t)));
154                         break;
155                 case MUSE_TYPE_INT64:
156                         json_object_object_add(jobj, name, json_object_new_int64(va_arg(ap, int64_t)));
157                         break;
158                 case MUSE_TYPE_POINTER:
159                         if (sizeof(intptr_t) == 8)
160                                 json_object_object_add(jobj, name, json_object_new_int64(va_arg(ap, intptr_t)));
161                         else
162                                 json_object_object_add(jobj, name, json_object_new_int(va_arg(ap, intptr_t)));
163                         break;
164                 case MUSE_TYPE_DOUBLE:
165                         json_object_object_add(jobj, name, json_object_new_double(va_arg(ap, double)));
166                         break;
167                 case MUSE_TYPE_STRING:
168                         json_object_object_add(jobj, name, json_object_new_string(va_arg(ap, char *)));
169                         break;
170                 case MUSE_TYPE_ARRAY:
171                         len = va_arg(ap, int);
172                         value = va_arg(ap, int *);
173                         jarr = json_object_new_array();
174
175                         for (idx = 0; idx < len; idx++)
176                                 json_object_array_add(jarr, json_object_new_int(value[idx]));
177                         json_object_object_add(jobj, name, jarr);
178                         break;
179                 default:
180                         LOGE("Unexpected type");
181                 }
182         }
183 }
184
185 static json_object *_muse_msg_json_find_obj(json_object *jobj, const char *find_key)
186 {
187         size_t key_len = 0;
188
189         muse_return_val_if_fail(jobj, NULL);
190
191         muse_return_val_if_fail(find_key, NULL);
192
193         key_len = strlen(find_key);
194
195         json_object_object_foreach(jobj, key, val) {
196                 if (strlen(key) == key_len && !memcmp(key, find_key, key_len))
197                         return val;
198         }
199
200         return NULL;
201 }
202
203 static gboolean _muse_msg_json_get_obj_value(json_object *obj, muse_core_msg_type_e m_type, void *data)
204 {
205         int j_type, idx, len;
206         int *int_data;
207         const char *src = NULL;
208
209         muse_return_val_if_fail(obj, FALSE);
210         muse_return_val_if_fail(data, FALSE);
211
212         j_type = json_object_get_type(obj);
213         switch (j_type) {
214         case json_type_null:
215                 LOGD("json_type_null");
216                 break;
217         case json_type_double:
218                 *(double *)data = json_object_get_double(obj);
219                 break;
220         case json_type_int:
221                 if (m_type == MUSE_TYPE_ANY || m_type == MUSE_TYPE_INT) {
222                         *(int32_t *)data = json_object_get_int(obj);
223                 } else if (m_type == MUSE_TYPE_INT64) {
224                         *(int64_t *)data = json_object_get_int64(obj);
225                 } else if (m_type == MUSE_TYPE_POINTER) {
226                         if (!_muse_msg_is_mem_ptr_valid(obj)) {
227                                 LOGE("memory pointer is not valid");
228                                 return FALSE;
229                         }
230                         if (sizeof(intptr_t) == 8)
231                                 *(intptr_t *)data = json_object_get_int64(obj);
232                         else
233                                 *(intptr_t *)data = json_object_get_int(obj);
234                 } else if (m_type == MUSE_TYPE_DOUBLE) {
235                         *(double *)data = json_object_get_double(obj);
236                 }
237                 break;
238         case json_type_object:
239                 break;
240         case json_type_string:
241                 src = json_object_get_string(obj);
242                 muse_return_val_if_fail(src, FALSE);
243                 g_strlcpy((gchar *)data, src, MUSE_MSG_MAX_LENGTH);
244                 break;
245         case json_type_array:
246                 int_data = (int *)data;
247                 len = json_object_array_length(obj);
248                 for (idx = 0; idx < len; idx++)
249                         int_data[idx] = json_object_get_int(json_object_array_get_idx(obj, idx));
250                 break;
251         default:
252                 LOGE("The value (%d) of json type is invalid", j_type);
253                 break;
254         }
255
256         return TRUE;
257 }
258
259 void muse_core_log_cmd_info(char *cmd)
260 {
261         FILE *fp;
262         char buf[MUSE_MSG_LEN_MAX];
263
264         muse_return_if_fail(cmd);
265
266         fp = popen(cmd, "r");
267
268         if (fp) {
269                 while (fgets(buf, MUSE_MSG_LEN_MAX, fp))
270                         LOGW("%s", buf);
271
272                 if (pclose(fp) == -1)
273                         LOGE("Fail to pclose");
274         }
275 }
276
277 bool muse_server_is_ready(void)
278 {
279         return access(MUSE_SERVER_READY, F_OK) == 0;
280 }
281
282 int muse_core_connection_close(int sock_fd)
283 {
284         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
285
286         if (!muse_core_fd_is_valid(sock_fd)) {
287                 LOGE("[%d] invalid socket", sock_fd);
288                 return MM_ERROR_INVALID_ARGUMENT;
289         }
290
291         if (shutdown(sock_fd, SHUT_RDWR) == MUSE_ERR) {
292                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
293                 LOGE("[%d] failed to shutdown [error %s %d]", sock_fd, err_msg, errno);
294         }
295
296         if (close(sock_fd) == MUSE_ERR) {
297                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
298                 LOGE("[%d] failed to close [error %s %d]", sock_fd, err_msg, errno);
299         }
300
301         muse_core_dump_fd_state(sock_fd);
302
303         g_mutex_lock(&fd_state_lock);
304
305         if (!g_hash_table_remove(fd_state_table, GINT_TO_POINTER(sock_fd)))
306                 LOGW("fail : remove fd %d from table[%p]", sock_fd, fd_state_table);
307
308         g_mutex_unlock(&fd_state_lock);
309
310         return MM_ERROR_NONE;
311 }
312
313 int muse_core_set_nonblocking(int fd, bool value)
314 {
315         int flags = fcntl(fd, F_GETFL, NULL);
316         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
317
318         if (flags >= 0) {
319                 flags = value ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK);
320                 if (fcntl(fd, F_SETFL, flags) == -1) {
321                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
322                         LOGE("fcntl (%d, F_SETFL, %d) [error %s %d]", fd, flags, err_msg, errno);
323                         return MM_ERROR_FILE_INTERNAL;
324                 } else {
325                         LOGD("fcntl (%d, F_SETFL)", fd);
326                 }
327         } else {
328                 LOGE("failed to get flags for %d", fd);
329                 return MM_ERROR_FILE_INTERNAL;
330         }
331
332         return MM_ERROR_NONE;
333 }
334
335 int muse_core_set_socket_timeout(int sock_fd, int timeout_sec)
336 {
337         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
338         struct timeval tv;
339
340         LOGD("Enter");
341
342         tv.tv_sec = timeout_sec;
343         tv.tv_usec = 0L;
344
345         if (setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, (socklen_t)sizeof(tv)) == MUSE_ERR) {
346                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
347                 LOGE("[%d] Failed to set socket send timeout option [error %s %d]", sock_fd, err_msg, errno);
348                 return MM_ERROR_UNKNOWN;
349         }
350
351         if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, (socklen_t)sizeof(tv)) == MUSE_ERR) {
352                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
353                 LOGE("[%d] Failed to set socket recv timeout option [error %s %d]", sock_fd, err_msg, errno);
354                 return MM_ERROR_UNKNOWN;
355         }
356
357         LOGD("Leave");
358
359         return MM_ERROR_NONE;
360 }
361
362 bool muse_core_fd_is_valid(int fd)
363 {
364         muse_core_update_fd_state(fd);
365         return (fcntl(fd, F_GETFL) != MUSE_ERR || errno != EBADF) && (fd > STDERR_FILENO);
366 }
367
368 void muse_core_fd_close(int fd)
369 {
370         if (!muse_core_fd_is_valid(fd)) {
371                 LOGW("%d is invalid fd", fd);
372                 return;
373         }
374
375         close(fd);
376 }
377
378 /* message */
379 int muse_core_msg_send(int sock_fd, const char *msg)
380 {
381         muse_return_val_if_fail(msg, MM_ERROR_INVALID_ARGUMENT);
382         return muse_core_msg_send_fd(sock_fd, NULL, msg);
383 }
384
385 int muse_core_msg_send_fd(int sock_fd, int *fds, const char *buf)
386 {
387         int ret = MM_ERROR_NONE;
388         muse_msg_info_t msg_info = {0,};
389         struct cmsghdr *cptr;
390         struct msghdr msg;
391         struct iovec iov;
392         char data[CMSG_SPACE(sizeof(int) * MUSE_NUM_FD)];
393         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
394         int *fdptr;
395         int fd_cnt = 0;
396
397         muse_return_val_if_fail(buf, MM_ERROR_INVALID_ARGUMENT);
398         muse_return_val_if_fail(muse_core_fd_is_valid(sock_fd), MM_ERROR_INVALID_ARGUMENT);
399
400         if (!fds)
401                 msg_info.type = MUSE_MSG_TYPE_NORMAL;
402         else
403                 msg_info.type = MUSE_MSG_TYPE_FDS;
404
405         msg_info.marker = MUSE_MSG_HEAD;
406         msg_info.size = strlen(buf);
407
408         g_mutex_lock(&msg_ipc_lock);
409
410         ret = send(sock_fd, &msg_info, sizeof(muse_msg_info_t), 0);
411         if (ret != sizeof(muse_msg_info_t)) {
412                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
413                 LOGE("msg info [type : %s size : %d] send failed : %d [error %s %d]",
414                                 msg_type[msg_info.type], msg_info.size, ret, err_msg, errno);
415
416                 goto _MSG_SEND_DONE;
417         }
418
419         if (msg_info.type == MUSE_MSG_TYPE_NORMAL) {
420                 ret = send(sock_fd, buf, msg_info.size, 0);
421                 if (ret != (int)msg_info.size) {
422                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
423                         LOGE("[%s] send failed : %d [error %s %d]", buf, ret, err_msg, errno);
424                 }
425
426                 goto _MSG_SEND_DONE;
427         }
428
429         /* MUSE_MSG_TYPE_FDS */
430         memset(&iov, 0, sizeof(iov));
431         iov.iov_base = (void *)buf;
432         iov.iov_len = msg_info.size;
433
434         memset(&msg, 0, sizeof(msg));
435         msg.msg_name = NULL;
436         msg.msg_namelen = 0;
437         msg.msg_iov = &iov;
438         msg.msg_iovlen = 1;
439
440         msg.msg_control = data;
441         msg.msg_controllen = sizeof(data);
442
443         cptr = CMSG_FIRSTHDR(&msg);
444         if (cptr) {
445                 fd_cnt = _muse_get_valid_fd_count(fds);
446                 cptr->cmsg_len = CMSG_LEN(sizeof(int) * fd_cnt);
447                 cptr->cmsg_level = SOL_SOCKET;
448                 cptr->cmsg_type = SCM_RIGHTS;
449                 fdptr = (int *)CMSG_DATA(cptr);
450
451                 memcpy(fdptr, fds, sizeof(int) * fd_cnt);
452
453                 /* the value of msg_controllen increases after memcpy so reassigns the original value */
454                 msg.msg_controllen = cptr->cmsg_len;
455         }
456
457         if ((ret = sendmsg(sock_fd, &msg, 0)) == SEND_FAIL) {
458                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
459                 LOGE("[%d] fail to send msg - [error %s %d]", sock_fd, err_msg, errno);
460         }
461
462 _MSG_SEND_DONE:
463         g_mutex_unlock(&msg_ipc_lock);
464
465         return ret;
466 }
467
468 int muse_core_msg_recv(int sock_fd, char *msg, int msg_len)
469 {
470         muse_return_val_if_fail(msg, MM_ERROR_INVALID_ARGUMENT);
471         return muse_core_msg_recv_fd(sock_fd, msg, msg_len, NULL);
472 }
473
474 int muse_core_msg_recv_fd(int sock_fd, char *buf, int buf_len, int *out_fd)
475 {
476         int ret = 0;
477         int pid;
478         struct cmsghdr *cptr;
479         struct msghdr msg;
480         struct iovec iov;
481         muse_msg_info_t msg_info = {0,};
482         char data[CMSG_SPACE(sizeof(int) * MUSE_NUM_FD)];
483         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
484
485         muse_return_val_if_fail(buf, MM_ERROR_INVALID_ARGUMENT);
486         muse_return_val_if_fail(muse_core_fd_is_valid(sock_fd), MM_ERROR_INVALID_ARGUMENT);
487
488         /* get the msg type and length */
489         if (!muse_core_msg_recv_len(sock_fd, (char *)&msg_info, sizeof(muse_msg_info_t))) {
490                 pid = (int)getpid();
491                 LOGE("[pid : %d] [fd : %d] msg info receive failed", pid, sock_fd);
492                 muse_core_log_process_thread_info(pid);
493                 return RECV_FAIL;
494         }
495
496         if (msg_info.size > 0 && buf_len < msg_info.size) {
497                 LOGE("stack overflow caution !! [recv buf's length (%d) must be larger than msg's length (%d)", buf_len, msg_info.size);
498                 return RECV_FAIL;
499         }
500
501         if (msg_info.marker != MUSE_MSG_HEAD) {
502                 LOGE("invalid marker 0x%x", msg_info.marker);
503                 return RECV_FAIL;
504         }
505
506         if (msg_info.type == MUSE_MSG_TYPE_NORMAL) {
507                 if (!muse_core_msg_recv_len(sock_fd, buf, msg_info.size)) {
508                         LOGE("msg receive failed");
509                         return RECV_FAIL;
510                 }
511
512                 ret = msg_info.size;
513         } else {
514                 memset(&iov, 0, sizeof(iov));
515                 iov.iov_base = (void *)buf;
516                 iov.iov_len = msg_info.size;
517
518                 memset(&msg, 0, sizeof(msg));
519                 msg.msg_name = NULL;
520                 msg.msg_namelen = 0;
521                 msg.msg_iov = &iov;
522                 msg.msg_iovlen = 1;
523                 msg.msg_control = data;
524                 msg.msg_controllen = sizeof(data);
525
526                 if ((ret = recvmsg(sock_fd, &msg, 0)) == RECV_FAIL) {
527                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
528                         LOGE("fail to receive msg [error %s %d]", err_msg, errno);
529                         return ret;
530                 }
531
532                 if (out_fd) {
533                         cptr = CMSG_FIRSTHDR(&msg);
534                         if (cptr)
535                                 memcpy(out_fd, CMSG_DATA(cptr), cptr->cmsg_len - CMSG_LEN(0));
536                 }
537         }
538
539         buf[ret] = '\0';
540
541         return ret;
542 }
543
544 char *muse_core_msg_new(int api, ...)
545 {
546         json_object *jobj;
547         const char *jsonMsg;
548         char *sndMsg;
549         va_list ap;
550
551         jobj = json_object_new_object();
552
553         muse_return_val_if_fail(jobj, NULL);
554
555         json_object_object_add(jobj, MSG_KEY_API, json_object_new_int(api));
556
557         va_start(ap, api);
558         _muse_msg_json_factory_args(jobj, ap);
559         va_end(ap);
560
561         jsonMsg = json_object_to_json_string(jobj);
562         sndMsg = g_strdup(jsonMsg);
563
564         if (api == API_CREATE)
565                 SECURE_LOGD("%s", sndMsg);
566
567         json_object_put(jobj);
568
569         return sndMsg;
570 }
571
572 bool muse_core_msg_deserialize(const char *key, char *buf, int *parse_len,
573                 muse_core_msg_parse_err_e *err, muse_core_msg_type_e m_type, void *data)
574 {
575         json_object *obj = NULL, *jobj = NULL;
576         bool ret = false;
577
578         muse_return_val_if_fail(key, false);
579         muse_return_val_if_fail(buf, false);
580         muse_return_val_if_fail(m_type >= MUSE_TYPE_INT && m_type < MUSE_TYPE_MAX, false);
581         muse_return_val_if_fail(data, false);
582
583         g_mutex_lock(&msg_lock);
584
585         jobj = _muse_msg_json_tokener_parse_len(buf, parse_len, err);
586         if (!jobj) {
587                 LOGE("jobj is NULL");
588                 g_mutex_unlock(&msg_lock);
589                 return false;
590         }
591
592         obj = _muse_msg_json_find_obj(jobj, key);
593         if (!obj) {
594                 LOGE("\"%s\" key is not founded", key);
595                 json_object_put(jobj);
596                 g_mutex_unlock(&msg_lock);
597                 return false;
598         }
599
600         ret = (bool)_muse_msg_json_get_obj_value(obj, m_type, data);
601
602         json_object_put(jobj);
603
604         g_mutex_unlock(&msg_lock);
605
606         return ret;
607 }
608
609 void muse_core_msg_free(char *msg)
610 {
611         MUSE_G_FREE(msg);
612 }
613
614 void *muse_core_msg_object_new(char *str, int *parse_len, muse_core_msg_parse_err_e *err)
615 {
616         void *jobj = NULL;
617
618         muse_return_val_if_fail(str, NULL);
619
620         g_mutex_lock(&msg_lock);
621
622         jobj = (void *)_muse_msg_json_tokener_parse_len(str, parse_len, err);
623
624         g_mutex_unlock(&msg_lock);
625
626         return jobj;
627 }
628
629 bool muse_core_msg_object_get_value(const char *key, void *jobj, muse_core_msg_type_e m_type, void *data)
630 {
631         json_object *obj;
632         bool ret = false;
633
634         muse_return_val_if_fail(key, false);
635         muse_return_val_if_fail(jobj, false);
636         muse_return_val_if_fail(data, false);
637         muse_return_val_if_fail(m_type >= MUSE_TYPE_INT && m_type < MUSE_TYPE_MAX, false);
638
639         g_mutex_lock(&msg_lock);
640
641         obj = _muse_msg_json_find_obj((json_object *)jobj, key);
642         if (!obj) {
643                 LOGE("\"%s\" key is not found", key);
644                 g_mutex_unlock(&msg_lock);
645                 return false;
646         }
647
648         ret = (bool)_muse_msg_json_get_obj_value(obj, m_type, data);
649
650         g_mutex_unlock(&msg_lock);
651
652         return ret;
653 }
654
655 void muse_core_msg_object_free(void *jobj)
656 {
657         muse_return_if_fail(jobj);
658
659         g_mutex_lock(&msg_lock);
660
661         json_object_put((json_object *)jobj);
662
663         g_mutex_unlock(&msg_lock);
664 }
665
666 bool muse_core_msg_recv_len(int fd, char *buf, int msg_len)
667 {
668         int offset = 0;
669         int recv_len = 0;
670         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
671
672         if (!muse_core_fd_is_valid(fd) || !buf || msg_len <= 0) {
673                 LOGE("invalid param : fd %d, buf %p, msg_len %d", fd, buf, msg_len);
674                 return false;
675         }
676
677         do {
678                 recv_len = recv(fd, buf + offset, msg_len - offset, 0);
679                 if (recv_len < 0) {
680                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
681                         LOGE("[%d] recv failed [error %s %d]", fd, err_msg, errno);
682                         return false;
683                 } else if (recv_len == 0) {
684                         LOGD("[%d] EOF", fd);
685                         return false;
686                 }
687
688                 offset += recv_len;
689         } while (offset < msg_len);
690
691         if (offset != msg_len) {
692                 LOGE("invalid length received : try %d -> result %d", msg_len, offset);
693                 return false;
694         }
695
696         return true;
697 }
698
699 void muse_core_change_time_format(int val, char *time_buf)
700 {
701         int sec, min, hour, day;
702
703         muse_return_if_fail(time_buf);
704
705         min = val / MUSE_MIN_SEC_VALUE;
706         hour = min / MUSE_HOUR_MIN_VALUE;
707         day = hour / MUSE_DAY_HOUR_VALUE;
708
709         sec = val % MUSE_MIN_SEC_VALUE;
710         min = min % MUSE_HOUR_MIN_VALUE;
711         hour = hour % MUSE_DAY_HOUR_VALUE;
712
713         snprintf(time_buf, MUSE_MSG_TIME_LEN, "%dd %dh %dm %ds", day, hour, min, sec);
714 }
715
716 void muse_core_dump_fd_state(int fd)
717 {
718         int sec = 0;
719         char time_buf[MUSE_MSG_TIME_LEN];
720
721         g_mutex_lock(&fd_state_lock);
722         sec = GPOINTER_TO_INT(g_hash_table_lookup(fd_state_table, GINT_TO_POINTER(fd)));
723         muse_core_change_time_format(sec, time_buf);
724         LOGI("[%d] %s", fd, time_buf);
725         g_mutex_unlock(&fd_state_lock);
726 }
727
728 void muse_core_update_fd_state(int fd)
729 {
730         struct timespec tv;
731
732         g_mutex_lock(&fd_state_lock);
733
734         if (!fd_state_table)
735                 fd_state_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
736
737         muse_core_get_cur_time(&tv, NULL);
738         g_hash_table_insert(fd_state_table, GINT_TO_POINTER(fd), GINT_TO_POINTER((int)tv.tv_sec));
739
740         g_mutex_unlock(&fd_state_lock);
741 }
742
743 void muse_core_create_fd_table(void)
744 {
745         g_mutex_lock(&fd_state_lock);
746
747         if (fd_state_table) {
748                 LOGW("fd state table [%p] is already created", fd_state_table);
749                 goto out;
750         }
751
752         fd_state_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
753         if (!fd_state_table)
754                 LOGE("fail to create new fd state table");
755 out:
756         g_mutex_unlock(&fd_state_lock);
757 }
758
759 void muse_core_remove_all_fd_table(void)
760 {
761         g_mutex_lock(&fd_state_lock);
762         g_hash_table_remove_all(fd_state_table);
763         g_mutex_unlock(&fd_state_lock);
764 }
765
766 void muse_core_destroy_fd_table(void)
767 {
768         g_mutex_lock(&fd_state_lock);
769         g_hash_table_destroy(fd_state_table);
770         fd_state_table = NULL;
771         g_mutex_unlock(&fd_state_lock);
772 }
773
774 void muse_core_get_cur_time(struct timespec *time, char *time_buf)
775 {
776         char cur_time[MUSE_MSG_LEN];
777         struct tm newtime;
778         struct timespec tv;
779
780         muse_return_if_fail(clock_gettime(CLOCK_MONOTONIC, &tv) == 0);
781
782         if (time)
783                 *time = tv;
784
785         if (time_buf) {
786                 strftime(cur_time, MUSE_MSG_LEN, STR_TIME_FORMAT, localtime_r(&(tv.tv_sec), &newtime));
787                 snprintf(time_buf, MUSE_MSG_TIME_LEN, "%s.%03ld", cur_time, tv.tv_nsec);
788         }
789 }
790
791 void muse_core_log_process_thread_info(int pid)
792 {
793         char cmd[MUSE_MSG_LEN_MAX];
794
795         snprintf(cmd, sizeof(cmd), "/bin/cat /proc/%d/status | /bin/grep Threads", pid);
796         muse_core_log_cmd_info(cmd);
797 }
798
799 void muse_core_log_process_opened_fds(int pid)
800 {
801         char dir_path[MUSE_MSG_LEN_MAX];
802         struct dirent *de = NULL;
803         DIR *dr = NULL;
804
805         snprintf(dir_path, sizeof(dir_path), "/proc/%d/fd", pid); /* /proc/%d/fd is directory */
806         dr = opendir(dir_path);
807         muse_return_if_fail(dr);
808
809         LOGI("directory path : %s", dir_path);
810
811         while ((de = readdir(dr)) != NULL)
812                 LOGW("%s\n", de->d_name);
813
814         closedir(dr);
815 }
816
817 void muse_core_log_process_cpu_memory(int pid)
818 {
819         char cmd[MUSE_MSG_LEN_MAX];
820
821         snprintf(cmd, sizeof(cmd), "/bin/ps -Lo pcpu,pmem,tid,comm -p %d", pid);
822         muse_core_log_cmd_info(cmd);
823 }
824
825 int muse_core_get_process_cpu_usage(int pid)
826 {
827         FILE *fp = NULL;
828         int cpu = 0;
829         char cmd[MUSE_MSG_LEN_MAX];
830         char buf[MUSE_MSG_LEN_MAX];
831
832         snprintf(cmd, sizeof(cmd), "/bin/ps -Lo pcpu,pmem,tid,comm -p %d", pid);
833
834         fp = popen(cmd, "r");
835
836         if (fp) {
837                 while (fgets(buf, MUSE_MSG_LEN_MAX, fp)) {
838                         LOGI("%s", buf);
839                         cpu += atoi(g_strstrip(buf));
840                 }
841
842                 if (pclose(fp) == -1)
843                         LOGE("Fail to pclose");
844         }
845
846         return cpu;
847 }
848
849 void muse_core_log_file_list(const char *path)
850 {
851         char cmd[MUSE_MSG_LEN_MAX];
852
853         snprintf(cmd, sizeof(cmd), "/bin/ls -alt %s", path);
854         muse_core_log_cmd_info(cmd);
855 }
856
857 void muse_core_remove_symlink(const char *path)
858 {
859         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
860         char *r = NULL;
861
862         muse_return_if_fail(path);
863
864         r = realpath(path, NULL);
865         if (r) {
866                 if (strncmp(r, path, strlen(path)) != 0) {
867                         LOGW("symbolic link exists [%s] -> [%s]", path, r);
868                         unlink(path);
869                 }
870                 free(r);
871         } else {
872                 if (errno != ENOENT) {
873                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
874                         LOGE("realpath failed [error %s %d]", err_msg, errno);
875                 }
876         }
877 }
878