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