Revise the time buffer array size
[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                 if (sock_fd != STDIN_FILENO)
288                         LOGE("[%d] invalid socket", sock_fd);
289                 return MM_ERROR_INVALID_ARGUMENT;
290         }
291
292         if (shutdown(sock_fd, SHUT_RDWR) == MUSE_ERR) {
293                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
294                 LOGE("[%d] failed to shutdown [error %s %d]", sock_fd, err_msg, errno);
295         }
296
297         if (close(sock_fd) == MUSE_ERR) {
298                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
299                 LOGE("[%d] failed to close [error %s %d]", sock_fd, err_msg, errno);
300         }
301
302         muse_core_dump_fd_state(sock_fd);
303
304         g_mutex_lock(&fd_state_lock);
305
306         if (!g_hash_table_remove(fd_state_table, GINT_TO_POINTER(sock_fd)))
307                 LOGW("fail : remove fd %d from table[%p]", sock_fd, fd_state_table);
308
309         g_mutex_unlock(&fd_state_lock);
310
311         return MM_ERROR_NONE;
312 }
313
314 int muse_core_set_nonblocking(int fd, bool value)
315 {
316         int flags = fcntl(fd, F_GETFL, NULL);
317         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
318
319         if (flags >= 0) {
320                 flags = value ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK);
321                 if (fcntl(fd, F_SETFL, flags) == -1) {
322                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
323                         LOGE("fcntl (%d, F_SETFL, %d) [error %s %d]", fd, flags, err_msg, errno);
324                         return MM_ERROR_FILE_INTERNAL;
325                 } else {
326                         LOGD("fcntl (%d, F_SETFL)", fd);
327                 }
328         } else {
329                 LOGE("failed to get flags for %d", fd);
330                 return MM_ERROR_FILE_INTERNAL;
331         }
332
333         return MM_ERROR_NONE;
334 }
335
336 int muse_core_set_socket_timeout(int sock_fd, int timeout_sec)
337 {
338         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
339         struct timeval tv;
340
341         LOGD("Enter");
342
343         tv.tv_sec = timeout_sec;
344         tv.tv_usec = 0L;
345
346         if (setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, (socklen_t)sizeof(tv)) == MUSE_ERR) {
347                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
348                 LOGE("[%d] Failed to set socket send timeout option [error %s %d]", sock_fd, err_msg, errno);
349                 return MM_ERROR_UNKNOWN;
350         }
351
352         if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, (socklen_t)sizeof(tv)) == MUSE_ERR) {
353                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
354                 LOGE("[%d] Failed to set socket recv timeout option [error %s %d]", sock_fd, err_msg, errno);
355                 return MM_ERROR_UNKNOWN;
356         }
357
358         LOGD("Leave");
359
360         return MM_ERROR_NONE;
361 }
362
363 bool muse_core_fd_is_valid(int fd)
364 {
365         muse_core_update_fd_state(fd);
366         return (fcntl(fd, F_GETFL) != MUSE_ERR || errno != EBADF) && (fd > STDERR_FILENO);
367 }
368
369 void muse_core_fd_close(int fd)
370 {
371         if (!muse_core_fd_is_valid(fd)) {
372                 LOGW("%d is invalid fd", fd);
373                 return;
374         }
375
376         close(fd);
377 }
378
379 /* message */
380 int muse_core_msg_send(int sock_fd, const char *msg)
381 {
382         muse_return_val_if_fail(msg, MM_ERROR_INVALID_ARGUMENT);
383         return muse_core_msg_send_fd(sock_fd, NULL, msg);
384 }
385
386 int muse_core_msg_send_fd(int sock_fd, int *fds, const char *buf)
387 {
388         int ret = MM_ERROR_NONE;
389         muse_msg_info_t msg_info = {0,};
390         struct cmsghdr *cptr;
391         struct msghdr msg;
392         struct iovec iov;
393         char data[CMSG_SPACE(sizeof(int) * MUSE_NUM_FD)];
394         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
395         int *fdptr;
396         int fd_cnt = 0;
397
398         muse_return_val_if_fail(buf, MM_ERROR_INVALID_ARGUMENT);
399         muse_return_val_if_fail(muse_core_fd_is_valid(sock_fd), MM_ERROR_INVALID_ARGUMENT);
400
401         if (!fds)
402                 msg_info.type = MUSE_MSG_TYPE_NORMAL;
403         else
404                 msg_info.type = MUSE_MSG_TYPE_FDS;
405
406         msg_info.marker = MUSE_MSG_HEAD;
407         msg_info.size = strlen(buf);
408
409         g_mutex_lock(&msg_ipc_lock);
410
411         ret = send(sock_fd, &msg_info, sizeof(muse_msg_info_t), 0);
412         if (ret != sizeof(muse_msg_info_t)) {
413                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
414                 LOGE("msg info [type : %s size : %d] send failed : %d [error %s %d]",
415                                 msg_type[msg_info.type], msg_info.size, ret, err_msg, errno);
416
417                 goto _MSG_SEND_DONE;
418         }
419
420         if (msg_info.type == MUSE_MSG_TYPE_NORMAL) {
421                 ret = send(sock_fd, buf, msg_info.size, 0);
422                 if (ret != (int)msg_info.size) {
423                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
424                         LOGE("[%s] send failed : %d [error %s %d]", buf, ret, err_msg, errno);
425                 }
426
427                 goto _MSG_SEND_DONE;
428         }
429
430         /* MUSE_MSG_TYPE_FDS */
431         memset(&iov, 0, sizeof(iov));
432         iov.iov_base = (void *)buf;
433         iov.iov_len = msg_info.size;
434
435         memset(&msg, 0, sizeof(msg));
436         msg.msg_name = NULL;
437         msg.msg_namelen = 0;
438         msg.msg_iov = &iov;
439         msg.msg_iovlen = 1;
440
441         msg.msg_control = data;
442         msg.msg_controllen = sizeof(data);
443
444         cptr = CMSG_FIRSTHDR(&msg);
445         if (cptr) {
446                 fd_cnt = _muse_get_valid_fd_count(fds);
447                 cptr->cmsg_len = CMSG_LEN(sizeof(int) * fd_cnt);
448                 cptr->cmsg_level = SOL_SOCKET;
449                 cptr->cmsg_type = SCM_RIGHTS;
450                 fdptr = (int *)CMSG_DATA(cptr);
451
452                 memcpy(fdptr, fds, sizeof(int) * fd_cnt);
453
454                 /* the value of msg_controllen increases after memcpy so reassigns the original value */
455                 msg.msg_controllen = cptr->cmsg_len;
456         }
457
458         if ((ret = sendmsg(sock_fd, &msg, 0)) == SEND_FAIL) {
459                 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
460                 LOGE("[%d] fail to send msg - [error %s %d]", sock_fd, err_msg, errno);
461         }
462
463 _MSG_SEND_DONE:
464         g_mutex_unlock(&msg_ipc_lock);
465
466         return ret;
467 }
468
469 int muse_core_msg_recv(int sock_fd, char *msg, int msg_len)
470 {
471         muse_return_val_if_fail(msg, MM_ERROR_INVALID_ARGUMENT);
472         return muse_core_msg_recv_fd(sock_fd, msg, msg_len, NULL);
473 }
474
475 int muse_core_msg_recv_fd(int sock_fd, char *buf, int buf_len, int *out_fd)
476 {
477         int ret = 0;
478         int pid;
479         struct cmsghdr *cptr;
480         struct msghdr msg;
481         struct iovec iov;
482         muse_msg_info_t msg_info = {0,};
483         char data[CMSG_SPACE(sizeof(int) * MUSE_NUM_FD)];
484         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
485
486         muse_return_val_if_fail(buf, MM_ERROR_INVALID_ARGUMENT);
487         muse_return_val_if_fail(muse_core_fd_is_valid(sock_fd), MM_ERROR_INVALID_ARGUMENT);
488
489         /* get the msg type and length */
490         if (!muse_core_msg_recv_len(sock_fd, (char *)&msg_info, sizeof(muse_msg_info_t))) {
491                 pid = (int)getpid();
492                 LOGE("[pid : %d] [fd : %d] msg info receive failed", pid, sock_fd);
493                 muse_core_log_process_thread_info(pid);
494                 return RECV_FAIL;
495         }
496
497         if (msg_info.size > 0 && buf_len < msg_info.size) {
498                 LOGE("stack overflow caution !! [recv buf's length (%d) must be larger than msg's length (%d)", buf_len, msg_info.size);
499                 return RECV_FAIL;
500         }
501
502         if (msg_info.marker != MUSE_MSG_HEAD) {
503                 LOGE("invalid marker 0x%x", msg_info.marker);
504                 return RECV_FAIL;
505         }
506
507         if (msg_info.type == MUSE_MSG_TYPE_NORMAL) {
508                 if (!muse_core_msg_recv_len(sock_fd, buf, msg_info.size)) {
509                         LOGE("msg receive failed");
510                         return RECV_FAIL;
511                 }
512
513                 ret = msg_info.size;
514         } else {
515                 memset(&iov, 0, sizeof(iov));
516                 iov.iov_base = (void *)buf;
517                 iov.iov_len = msg_info.size;
518
519                 memset(&msg, 0, sizeof(msg));
520                 msg.msg_name = NULL;
521                 msg.msg_namelen = 0;
522                 msg.msg_iov = &iov;
523                 msg.msg_iovlen = 1;
524                 msg.msg_control = data;
525                 msg.msg_controllen = sizeof(data);
526
527                 if ((ret = recvmsg(sock_fd, &msg, 0)) == RECV_FAIL) {
528                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
529                         LOGE("fail to receive msg [error %s %d]", err_msg, errno);
530                         return ret;
531                 }
532
533                 if (out_fd) {
534                         cptr = CMSG_FIRSTHDR(&msg);
535                         if (cptr)
536                                 memcpy(out_fd, CMSG_DATA(cptr), cptr->cmsg_len - CMSG_LEN(0));
537                 }
538         }
539
540         buf[ret] = '\0';
541
542         return ret;
543 }
544
545 char *muse_core_msg_new(int api, ...)
546 {
547         json_object *jobj;
548         const char *jsonMsg;
549         char *sndMsg;
550         va_list ap;
551
552         jobj = json_object_new_object();
553
554         muse_return_val_if_fail(jobj, NULL);
555
556         json_object_object_add(jobj, MSG_KEY_API, json_object_new_int(api));
557
558         va_start(ap, api);
559         _muse_msg_json_factory_args(jobj, ap);
560         va_end(ap);
561
562         jsonMsg = json_object_to_json_string(jobj);
563         sndMsg = g_strdup(jsonMsg);
564
565         if (api == API_CREATE)
566                 SECURE_LOGD("%s", sndMsg);
567
568         json_object_put(jobj);
569
570         return sndMsg;
571 }
572
573 bool muse_core_msg_deserialize(const char *key, char *buf, int *parse_len,
574                 muse_core_msg_parse_err_e *err, muse_core_msg_type_e m_type, void *data)
575 {
576         json_object *obj = NULL, *jobj = NULL;
577         bool ret = false;
578
579         muse_return_val_if_fail(key, false);
580         muse_return_val_if_fail(buf, false);
581         muse_return_val_if_fail(m_type >= MUSE_TYPE_INT && m_type < MUSE_TYPE_MAX, false);
582         muse_return_val_if_fail(data, false);
583
584         g_mutex_lock(&msg_lock);
585
586         jobj = _muse_msg_json_tokener_parse_len(buf, parse_len, err);
587         if (!jobj) {
588                 LOGE("jobj is NULL");
589                 g_mutex_unlock(&msg_lock);
590                 return false;
591         }
592
593         obj = _muse_msg_json_find_obj(jobj, key);
594         if (!obj) {
595                 LOGE("\"%s\" key is not founded", key);
596                 json_object_put(jobj);
597                 g_mutex_unlock(&msg_lock);
598                 return false;
599         }
600
601         ret = (bool)_muse_msg_json_get_obj_value(obj, m_type, data);
602
603         json_object_put(jobj);
604
605         g_mutex_unlock(&msg_lock);
606
607         return ret;
608 }
609
610 void muse_core_msg_free(char *msg)
611 {
612         MUSE_G_FREE(msg);
613 }
614
615 void *muse_core_msg_object_new(char *str, int *parse_len, muse_core_msg_parse_err_e *err)
616 {
617         void *jobj = NULL;
618
619         muse_return_val_if_fail(str, NULL);
620
621         g_mutex_lock(&msg_lock);
622
623         jobj = (void *)_muse_msg_json_tokener_parse_len(str, parse_len, err);
624
625         g_mutex_unlock(&msg_lock);
626
627         return jobj;
628 }
629
630 bool muse_core_msg_object_get_value(const char *key, void *jobj, muse_core_msg_type_e m_type, void *data)
631 {
632         json_object *obj;
633         bool ret = false;
634
635         muse_return_val_if_fail(key, false);
636         muse_return_val_if_fail(jobj, false);
637         muse_return_val_if_fail(data, false);
638         muse_return_val_if_fail(m_type >= MUSE_TYPE_INT && m_type < MUSE_TYPE_MAX, false);
639
640         g_mutex_lock(&msg_lock);
641
642         obj = _muse_msg_json_find_obj((json_object *)jobj, key);
643         if (!obj) {
644                 LOGE("\"%s\" key is not found", key);
645                 g_mutex_unlock(&msg_lock);
646                 return false;
647         }
648
649         ret = (bool)_muse_msg_json_get_obj_value(obj, m_type, data);
650
651         g_mutex_unlock(&msg_lock);
652
653         return ret;
654 }
655
656 void muse_core_msg_object_free(void *jobj)
657 {
658         muse_return_if_fail(jobj);
659
660         g_mutex_lock(&msg_lock);
661
662         json_object_put((json_object *)jobj);
663
664         g_mutex_unlock(&msg_lock);
665 }
666
667 bool muse_core_msg_recv_len(int fd, char *buf, int msg_len)
668 {
669         int offset = 0;
670         int recv_len = 0;
671         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
672
673         if (!muse_core_fd_is_valid(fd) || !buf || msg_len <= 0) {
674                 LOGE("invalid param : fd %d, buf %p, msg_len %d", fd, buf, msg_len);
675                 return false;
676         }
677
678         do {
679                 recv_len = recv(fd, buf + offset, msg_len - offset, 0);
680                 if (recv_len < 0) {
681                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
682                         LOGE("[%d] recv failed [error %s %d]", fd, err_msg, errno);
683                         return false;
684                 } else if (recv_len == 0) {
685                         LOGD("[%d] EOF", fd);
686                         return false;
687                 }
688
689                 offset += recv_len;
690         } while (offset < msg_len);
691
692         if (offset != msg_len) {
693                 LOGE("invalid length received : try %d -> result %d", msg_len, offset);
694                 return false;
695         }
696
697         return true;
698 }
699
700 void muse_core_change_time_format(int val, char *time_buf)
701 {
702         int sec, min, hour, day;
703
704         muse_return_if_fail(time_buf);
705
706         min = val / MUSE_MIN_SEC_VALUE;
707         hour = min / MUSE_HOUR_MIN_VALUE;
708         day = hour / MUSE_DAY_HOUR_VALUE;
709
710         sec = val % MUSE_MIN_SEC_VALUE;
711         min = min % MUSE_HOUR_MIN_VALUE;
712         hour = hour % MUSE_DAY_HOUR_VALUE;
713
714         snprintf(time_buf, MUSE_MSG_TIME_LEN, "%dd %dh %dm %ds", day, hour, min, sec);
715 }
716
717 void muse_core_dump_fd_state(int fd)
718 {
719         int sec = 0;
720         char time_buf[MUSE_MSG_TIME_LEN];
721
722         g_mutex_lock(&fd_state_lock);
723         sec = GPOINTER_TO_INT(g_hash_table_lookup(fd_state_table, GINT_TO_POINTER(fd)));
724         muse_core_change_time_format(sec, time_buf);
725         LOGI("[%d] %s", fd, time_buf);
726         g_mutex_unlock(&fd_state_lock);
727 }
728
729 void muse_core_update_fd_state(int fd)
730 {
731         struct timespec tv;
732
733         g_mutex_lock(&fd_state_lock);
734
735         if (!fd_state_table)
736                 fd_state_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
737
738         muse_core_get_cur_time(&tv, NULL);
739         g_hash_table_insert(fd_state_table, GINT_TO_POINTER(fd), GINT_TO_POINTER((int)tv.tv_sec));
740
741         g_mutex_unlock(&fd_state_lock);
742 }
743
744 void muse_core_create_fd_table(void)
745 {
746         g_mutex_lock(&fd_state_lock);
747
748         if (fd_state_table) {
749                 LOGW("fd state table [%p] is already created", fd_state_table);
750                 goto out;
751         }
752
753         fd_state_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
754         if (!fd_state_table)
755                 LOGE("fail to create new fd state table");
756 out:
757         g_mutex_unlock(&fd_state_lock);
758 }
759
760 void muse_core_remove_all_fd_table(void)
761 {
762         g_mutex_lock(&fd_state_lock);
763         g_hash_table_remove_all(fd_state_table);
764         g_mutex_unlock(&fd_state_lock);
765 }
766
767 void muse_core_destroy_fd_table(void)
768 {
769         g_mutex_lock(&fd_state_lock);
770         g_hash_table_destroy(fd_state_table);
771         fd_state_table = NULL;
772         g_mutex_unlock(&fd_state_lock);
773 }
774
775 void muse_core_get_cur_time(struct timespec *time, char *time_buf)
776 {
777         char cur_time[MUSE_MSG_LEN];
778         struct tm newtime;
779         struct timespec tv;
780
781         muse_return_if_fail(clock_gettime(CLOCK_MONOTONIC, &tv) == 0);
782
783         if (time)
784                 *time = tv;
785
786         if (time_buf) {
787                 strftime(cur_time, MUSE_MSG_LEN, STR_TIME_FORMAT, localtime_r(&(tv.tv_sec), &newtime));
788                 snprintf(time_buf, MUSE_MSG_TIME_LEN, "%s.%03ld", cur_time, tv.tv_nsec);
789         }
790 }
791
792 void muse_core_log_process_thread_info(int pid)
793 {
794         char cmd[MUSE_MSG_LEN_MAX];
795
796         snprintf(cmd, sizeof(cmd), "/bin/cat /proc/%d/status | /bin/grep Threads", pid);
797         muse_core_log_cmd_info(cmd);
798 }
799
800 void muse_core_log_process_opened_fds(int pid)
801 {
802         char dir_path[MUSE_MSG_LEN_MAX];
803         struct dirent *de = NULL;
804         DIR *dr = NULL;
805
806         snprintf(dir_path, sizeof(dir_path), "/proc/%d/fd", pid); /* /proc/%d/fd is directory */
807         dr = opendir(dir_path);
808         muse_return_if_fail(dr);
809
810         LOGI("directory path : %s", dir_path);
811
812         while ((de = readdir(dr)) != NULL)
813                 LOGW("%s\n", de->d_name);
814
815         closedir(dr);
816 }
817
818 void muse_core_log_process_cpu_memory(int pid)
819 {
820         char cmd[MUSE_MSG_LEN_MAX];
821
822         snprintf(cmd, sizeof(cmd), "/bin/ps -Lo pcpu,pmem,tid,comm -p %d", pid);
823         muse_core_log_cmd_info(cmd);
824 }
825
826 int muse_core_get_process_cpu_usage(int pid)
827 {
828         FILE *fp = NULL;
829         int cpu = 0;
830         char cmd[MUSE_MSG_LEN_MAX];
831         char buf[MUSE_MSG_LEN_MAX];
832
833         snprintf(cmd, sizeof(cmd), "/bin/ps -Lo pcpu,pmem,tid,comm -p %d", pid);
834
835         fp = popen(cmd, "r");
836
837         if (fp) {
838                 while (fgets(buf, MUSE_MSG_LEN_MAX, fp)) {
839                         LOGI("%s", buf);
840                         cpu += atoi(g_strstrip(buf));
841                 }
842
843                 if (pclose(fp) == -1)
844                         LOGE("Fail to pclose");
845         }
846
847         return cpu;
848 }
849
850 void muse_core_log_file_list(const char *path)
851 {
852         char cmd[MUSE_MSG_LEN_MAX];
853
854         snprintf(cmd, sizeof(cmd), "/bin/ls -alt %s", path);
855         muse_core_log_cmd_info(cmd);
856 }
857
858 void muse_core_remove_symlink(const char *path)
859 {
860         char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
861         char *r = NULL;
862
863         muse_return_if_fail(path);
864
865         r = realpath(path, NULL);
866         if (r) {
867                 if (strncmp(r, path, strlen(path) + 1) != 0) {
868                         LOGW("symbolic link exists [%s] -> [%s]", path, r);
869                         unlink(path);
870                 }
871                 free(r);
872         } else {
873                 if (errno != ENOENT) {
874                         strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
875                         LOGE("realpath failed [error %s %d]", err_msg, errno);
876                 }
877         }
878 }
879