diff options
author | 2018-03-08 17:39:22 -0800 | |
---|---|---|
committer | 2018-03-08 17:39:22 -0800 | |
commit | 697ade6190b23c80e7f60963983786e679759393 (patch) | |
tree | dd9782d1e936b8342163b26795e23571d4b1b415 /src/framework/ipc | |
parent | 71a4e2f34afa8018426f0e830050e50a1de6d375 (diff) |
dmm initial commit
Change-Id: I049ee277cf4efdb83f9c2ac439365fcd421c159b
Signed-off-by: qchang <qing.chang1@huawei.com>
Diffstat (limited to 'src/framework/ipc')
-rw-r--r-- | src/framework/ipc/mgr_com/mgr_com.c | 2037 | ||||
-rw-r--r-- | src/framework/ipc/mgr_com/mgr_com.h | 150 | ||||
-rw-r--r-- | src/framework/ipc/ps/nsfw_fd_timer.c | 378 | ||||
-rw-r--r-- | src/framework/ipc/ps/nsfw_ps_mem_module.c | 924 | ||||
-rw-r--r-- | src/framework/ipc/ps/nsfw_ps_mem_module.h | 87 | ||||
-rw-r--r-- | src/framework/ipc/ps/nsfw_ps_module.c | 1725 | ||||
-rw-r--r-- | src/framework/ipc/ps/nsfw_ps_module.h | 99 | ||||
-rw-r--r-- | src/framework/ipc/ps/nsfw_recycle_module.c | 666 | ||||
-rw-r--r-- | src/framework/ipc/ps/nsfw_recycle_module.h | 84 | ||||
-rw-r--r-- | src/framework/ipc/ps/nsfw_soft_param.c | 296 |
10 files changed, 6446 insertions, 0 deletions
diff --git a/src/framework/ipc/mgr_com/mgr_com.c b/src/framework/ipc/mgr_com/mgr_com.c new file mode 100644 index 0000000..4a57d6a --- /dev/null +++ b/src/framework/ipc/mgr_com/mgr_com.c @@ -0,0 +1,2037 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ + +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" +#include "common_mem_api.h" + +#include "nsfw_mgr_com_api.h" +#include "mgr_com.h" +#include "nstack_log.h" +#include "nsfw_base_linux_api.h" + +#include <sys/un.h> +#include <stddef.h> +#include <sys/epoll.h> +#include <fcntl.h> + +#include "nsfw_maintain_api.h" +#include "nsfw_ps_api.h" +#include "nsfw_fd_timer_api.h" + +#include "common_func.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +/* *INDENT-OFF* */ + +/* *INDENT-OFF* */ +nsfw_mgr_msg_fun g_mgr_fun[MGR_MSG_MAX][NSFW_MGRCOM_MAX_PROC_FUN]; +nsfw_mgr_init_cfg g_mgr_com_cfg; +nsfw_mgr_sock_map g_mgr_sockt_map = {{0}, NULL}; +nsfw_mgrcom_stat g_mgr_stat; +nsfw_mgrcom_proc g_ep_proc = { 0 }; +/* *INDENT-ON* */ + +u32 g_mgr_sockfdmax = NSFW_MGRCOM_MAX_SOCKET; + +char g_proc_info[NSFW_PROC_MAX][NSTACK_MAX_PROC_NAME_LEN] = { + "", "nStackMain", "nStackMaster", "nStackLib", "nStackTools", "nStackCtrl", + "", "", "", "", "", "", "", "", "", "" +}; + +/* *INDENT-ON* */ + +int g_thread_policy = 0; +int g_thread_pri = 0; + +void +nsfw_com_attr_set (int policy, int pri) +{ + g_thread_policy = policy; + g_thread_pri = pri; +} + +char * +nsfw_get_proc_name (u8 proc_type) +{ + if (proc_type >= NSFW_PROC_MAX || NSFW_PROC_NULL == proc_type) + { + return NULL; + } + + return g_proc_info[proc_type]; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_reg_msg_fun +* Description : reg the callback funciton when receive new message +* Input : u16 msg_type +* nsfw_mgr_msg_fun fun +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_reg_msg_fun (u16 msg_type, nsfw_mgr_msg_fun fun) +{ + u32 i; + if (MGR_MSG_MAX <= msg_type) + { + NSFW_LOGERR ("reg mgr_msg]msg_type=%u,fun=%p", msg_type, fun); + return FALSE; + } + + for (i = 0; i < NSFW_MGRCOM_MAX_PROC_FUN; i++) + { + if (NULL == g_mgr_fun[msg_type][i]) + { + /*TODO should use cas */ + g_mgr_fun[msg_type][i] = fun; + NSFW_LOGINF ("reg mgr_msg fun suc]msg_type=%u,fun=%p", msg_type, + fun); + return TRUE; + } + } + + NSFW_LOGERR ("reg mgr_msg type full]msg_type=%u,fun=%p", msg_type, fun); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_null_rspmsg_alloc +* Description : alloc null response msg for receive message buffer +* Input : None +* Output : None +* Return Value : nsfw_mgr_msg* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_mgr_msg * +nsfw_mgr_null_rspmsg_alloc () +{ + return nsfw_mgr_msg_alloc (MGR_MSG_NULL, NSFW_PROC_NULL); +} + +/***************************************************************************** +* Prototype : nsfw_mgr_msg_alloc +* Description : alloc new request message to send +* Input : u16 msg_type +* u8 dst_proc_type +* Output : None +* Return Value : nsfw_mgr_msg* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_mgr_msg * +nsfw_mgr_msg_alloc (u16 msg_type, u8 dst_proc_type) +{ + nsfw_mgr_msg *p_msg = NULL; + u8 from_mem_flag = FALSE; + u32 alloc_len = sizeof (nsfw_mgr_msg); + + if (MGR_MSG_LAG_QRY_RSP_BEGIN <= msg_type) + { + from_mem_flag = TRUE; + alloc_len = NSFW_MGR_LARGE_MSG_LEN; + } + + if ((NULL == g_mgr_com_cfg.msg_pool) + && (MGR_MSG_INIT_NTY_REQ == msg_type + || MGR_MSG_INIT_NTY_RSP == msg_type)) + { + from_mem_flag = TRUE; + } + + if (FALSE == from_mem_flag) + { + if (0 == + nsfw_mem_ring_dequeue (g_mgr_com_cfg.msg_pool, (void *) &p_msg)) + { + NSFW_LOGERR ("alloc msg full]type=%u,dst=%u", msg_type, + dst_proc_type); + return NULL; + } + alloc_len = sizeof (nsfw_mgr_msg); + } + else + { + p_msg = (nsfw_mgr_msg *) malloc (alloc_len); + } + + if (NULL == p_msg) + { + NSFW_LOGERR ("alloc msg nul]type=%u,dst=%u", msg_type, dst_proc_type); + return NULL; + } + + if (EOK != MEMSET_S (p_msg, alloc_len, 0, alloc_len)) + { + p_msg->from_mem = from_mem_flag; + nsfw_mgr_msg_free (p_msg); + NSFW_LOGERR ("alloc msg MEMSET_S failed]type=%u,dst=%u", msg_type, + dst_proc_type); + return NULL; + } + p_msg->from_mem = from_mem_flag; + + if (msg_type < MGR_MSG_RSP_BASE && msg_type > 0) + { + p_msg->seq = common_mem_atomic32_add_return (&g_mgr_com_cfg.cur_idx, 1); + } + + p_msg->from_mem = from_mem_flag; + p_msg->msg_type = msg_type; + p_msg->src_pid = get_sys_pid (); + p_msg->src_proc_type = g_mgr_com_cfg.proc_type; + p_msg->msg_len = alloc_len; + p_msg->dst_proc_type = dst_proc_type; + p_msg->alloc_flag = TRUE; + p_msg->more_msg_flag = 0; + + g_mgr_stat.msg_alloc++; + return p_msg; +} + +static inline void +lint_lock_1 () +{ + return; +} + +static inline void +lint_unlock_1 () +{ + return; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_rsp_msg_alloc +* Description : alloc response message from request message +* Input : nsfw_mgr_msg* req_msg +* Output : None +* Return Value : nsfw_mgr_msg* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_mgr_msg * +nsfw_mgr_rsp_msg_alloc (nsfw_mgr_msg * req_msg) +{ + nsfw_mgr_msg *p_msg = NULL; + if (NULL == req_msg) + { + NSFW_LOGERR ("req msg nul!"); + return NULL; + } + + p_msg = + nsfw_mgr_msg_alloc (req_msg->msg_type + MGR_MSG_RSP_BASE, + req_msg->src_proc_type); + if (NULL == p_msg) + { + return NULL; + } + + p_msg->dst_pid = req_msg->src_pid; + p_msg->seq = req_msg->seq; + return p_msg; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_msg_free +* Description : message free +* Input : nsfw_mgr_msg *msg +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_mgr_msg_free (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + return; + } + + if (FALSE == msg->alloc_flag) + { + NSFW_LOGERR ("msg refree]msg=%p, type=%u", msg, msg->msg_type); + return; + } + + msg->alloc_flag = FALSE; + + if (TRUE == msg->from_mem) + { + if ((MGR_MSG_INIT_NTY_REQ == msg->msg_type + || MGR_MSG_INIT_NTY_RSP == msg->msg_type) + || (MGR_MSG_LAG_QRY_RSP_BEGIN <= msg->msg_type)) + { + free (msg); + g_mgr_stat.msg_free++; + return; + } + NSFW_LOGERR ("msg err free]type=%u", msg->msg_type); + } + + if (0 == nsfw_mem_ring_enqueue (g_mgr_com_cfg.msg_pool, msg)) + { + NSFW_LOGERR ("msg free failed pool full]msg=%p, type=%u", msg, + msg->msg_type); + return; + } + + g_mgr_stat.msg_free++; + return; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_get_listen_socket +* Description : get domain socket listen fd +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mgr_get_listen_socket () +{ + i32 fd, len; + struct sockaddr_un un; + + if ((fd = nsfw_base_socket (AF_UNIX, SOCK_STREAM, 0)) < 0) + { + NSFW_LOGERR ("create sock failed!"); + return -1; + } + + if (-1 == unlink ((char *) g_mgr_com_cfg.domain_path)) + { + NSFW_LOGWAR ("unlink failed]error=%d", errno); + } + if (EOK != MEMSET_S (&un, sizeof (un), 0, sizeof (un))) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("create sock MEMSET_S failed!] error=%d", errno); + return -1; + } + + un.sun_family = AF_UNIX; + int retVal = STRCPY_S ((char *) un.sun_path, sizeof (un.sun_path), + (char *) g_mgr_com_cfg.domain_path); + if (EOK != retVal) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("create sock STRCPY_S failed!] error=%d", errno); + return -1; + } + + int rc = nsfw_set_close_on_exec (fd); + if (rc == -1) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", fd, errno); + return -1; + } + + len = + offsetof (struct sockaddr_un, + sun_path) +strlen ((char *) g_mgr_com_cfg.domain_path); + + if (nsfw_base_bind (fd, (struct sockaddr *) &un, len) < 0) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("bind failed!]mgr_fd=%d,error=%d", fd, errno); + return -1; + } + + if (nsfw_base_listen (fd, 10) < 0) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("listen failed!]mgr_fd=%d,error=%d", fd, errno); + return -1; + } + + NSFW_LOGINF ("mgr com start with]mgr_fd=%d", fd); + return fd; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_get_connect_socket +* Description : get new connect fd to destination procedure +* Input : u8 proc_type +* u32 host_pid +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mgr_get_connect_socket (u8 proc_type, u32 host_pid) +{ + i32 fd, len; + char *name; + struct sockaddr_un un; + const char *directory = NSFW_DOMAIN_DIR; + const char *home_dir = getenv ("HOME"); + + if (getuid () != 0 && home_dir != NULL) + directory = home_dir; + + switch (proc_type) + { + case NSFW_PROC_MAIN: + name = NSFW_MAIN_FILE; + break; + case NSFW_PROC_MASTER: + name = NSFW_MASTER_FILE; + break; + case NSFW_PROC_ALARM: + directory = "/tmp"; + name = NSFW_ALARM_FILE; + break; + default: + NSFW_LOGERR ("get dst socket err]type=%u,pid=%u", proc_type, host_pid); + return -1; + } + + if ((fd = nsfw_base_socket (AF_UNIX, SOCK_STREAM, 0)) < 0) + { + NSFW_LOGERR ("create socket err]type=%u,pid=%u,errno=%d", proc_type, + host_pid, errno); + return -1; + } + + if (EOK != MEMSET_S (&un, sizeof (un), 0, sizeof (un))) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("get dst socket err]mgr_fd=%d,type=%u,pid=%u", fd, + proc_type, host_pid); + return -1; + } + + struct timeval tv; + tv.tv_sec = MGR_COM_RECV_TIMEOUT; + tv.tv_usec = 0; + if (nsfw_base_setsockopt + (fd, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof tv)) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("setsockopt socket err]mgr_fd=%d,type=%u,pid=%u", fd, + proc_type, host_pid); + return -1; + } + + int rc = nsfw_set_close_on_exec (fd); + if (rc == -1) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", fd, errno); + return -1; + } + + int size, size_len; + size = MAX_RECV_BUF_DEF; + size_len = sizeof (size); + if (0 > + nsfw_base_setsockopt (fd, SOL_SOCKET, SO_RCVBUF, (void *) &size, + (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + if (0 > + nsfw_base_setsockopt (fd, SOL_SOCKET, SO_SNDBUF, (void *) &size, + (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + un.sun_family = AF_UNIX;; + int retVal = STRCPY_S ((char *) un.sun_path, sizeof (un.sun_path), + (char *) directory); + if (EOK != retVal) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("create sock STRCPY_S failed!] error=%d", errno); + return -1; + } + + retVal = STRCAT_S (un.sun_path, sizeof (un.sun_path), name); + if (EOK != retVal) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("create sock STRCAT_S failed!] error=%d", errno); + return -1; + } + + len = offsetof (struct sockaddr_un, sun_path) +strlen (un.sun_path); + if (nsfw_base_connect (fd, (struct sockaddr *) &un, len) < 0) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR + ("create socket err]mgr_fd=%d,type=%u,pid=%u,errno=%d,path=%s", fd, + proc_type, host_pid, errno, un.sun_path); + return -1; + } + + NSFW_LOGINF ("get dst socket]mgr_fd=%d,type=%u,pid=%u", fd, proc_type, + host_pid); + return (fd); +} + +/***************************************************************************** +* Prototype : nsfw_mgr_new_socket +* Description : management the new fd to cache +* Input : u32 fd +* u8 proc_type +* u32 host_pid +* Output : None +* Return Value : static inline u8 +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC inline u8 +nsfw_mgr_new_socket (i32 fd, u8 proc_type, u32 host_pid) +{ + nsfw_mgr_sock_info *sock_info = NULL; + if (((i32) NSFW_MGR_FD_MAX <= fd) || (fd < 0) || (!g_mgr_sockt_map.sock)) + { + NSFW_LOGERR ("fd err]mgr_fd=%d, sock=%p", fd, g_mgr_sockt_map.sock); + return FALSE; + } + + sock_info = &g_mgr_sockt_map.sock[fd]; + if (host_pid != sock_info->host_pid) + { + NSFW_LOGDBG + ("update sock info]mgr_fd=%d,old_pid=%u,new_pid=%u,type=%u", fd, + sock_info->host_pid, host_pid, proc_type); + } + + sock_info->host_pid = host_pid; + sock_info->proc_type = proc_type; + + if (proc_type < NSFW_PROC_MAX) + { + g_mgr_sockt_map.proc_cache[proc_type] = fd; + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_del_socket +* Description : delete the fd from cache when fd close +* Input : u32 fd +* Output : None +* Return Value : static inline u8 +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC inline u8 +nsfw_mgr_del_socket (u32 fd) +{ + nsfw_mgr_sock_info *sock_info = NULL; + if ((NSFW_MGR_FD_MAX <= fd) || (!g_mgr_sockt_map.sock)) + { + NSFW_LOGERR ("fd err]mgr_fd=%u, sock=%p", fd, g_mgr_sockt_map.sock); + return FALSE; + } + + sock_info = &g_mgr_sockt_map.sock[fd]; + + if (sock_info->proc_type < NSFW_PROC_MAX + && fd == g_mgr_sockt_map.proc_cache[sock_info->proc_type]) + { + g_mgr_sockt_map.proc_cache[sock_info->proc_type] = 0; + } + + NSFW_LOGDBG ("del sock]mgr_fd=%u,type=%u,pid=%u", fd, + sock_info->proc_type, sock_info->host_pid); + sock_info->host_pid = 0; + sock_info->proc_type = 0; + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_get_dst_socket +* Description : get the fd to send message to destination procedure +* Input : u8 proc_type +* u32 dst_pid +* Output : None +* Return Value : static inline i32 +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC inline i32 +nsfw_mgr_get_dst_socket (u8 proc_type, u32 dst_pid) +{ + i32 fd = -1; + + nsfw_mgr_sock_info *sock_info = NULL; + + if (proc_type < NSFW_PROC_MAX) + { + fd = g_mgr_sockt_map.proc_cache[proc_type]; + } + + if (!g_mgr_sockt_map.sock) + { + return -1; + } + + if (fd > 0 && fd < (i32) NSFW_MGR_FD_MAX) + { + sock_info = &g_mgr_sockt_map.sock[fd]; + if (sock_info->host_pid != 0) + { + if (0 == dst_pid || dst_pid == sock_info->host_pid) + { + return fd; + } + } + else if (proc_type == sock_info->proc_type) + { + return fd; + } + } + + i32 i; + for (i = 0; i < (i32) NSFW_MGR_FD_MAX; i++) + { + sock_info = &g_mgr_sockt_map.sock[i]; + if (sock_info->host_pid != 0 && proc_type == sock_info->proc_type) + { + if (0 == dst_pid || dst_pid == sock_info->host_pid) + { + return i; + } + } + } + + return -1; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_get_new_socket +* Description : get new connect +* Input : u8 proc_type +* u32 dst_pid +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mgr_get_new_socket (u8 proc_type, u32 dst_pid) +{ + i32 fd = 0; + fd = nsfw_mgr_get_connect_socket (proc_type, dst_pid); + if (fd > 0) + { + (void) nsfw_mgr_new_socket (fd, proc_type, dst_pid); + (void) nsfw_mgr_reg_sock_fun (fd, nsfw_mgr_new_msg); + } + return fd; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_clr_fd_lock +* Description : clear the fd lock when fork in child proc +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_clr_fd_lock () +{ + i32 i; + if (!g_mgr_sockt_map.sock) + { + NSFW_LOGERR ("clr fd lock fail, sock is null"); + return FALSE; + } + for (i = 0; i < (i32) NSFW_MGR_FD_MAX; i++) + { + common_mem_spinlock_init (&(g_mgr_sockt_map.sock[i].opr_lock)); + } + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_close_dst_proc +* Description : close the remote connect +* Input : u8 proc_type +* u32 dst_pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_mgr_close_dst_proc (u8 proc_type, u32 dst_pid) +{ + i32 fd = nsfw_mgr_get_dst_socket (proc_type, dst_pid); + if (fd > 0) + { + (void) nsfw_mgr_del_socket (fd); + (void) nsfw_mgr_unreg_sock_fun (fd); + (void) nsfw_base_close (fd); + } +} + +/***************************************************************************** +* Prototype : nsfw_mgr_send_msg_socket +* Description : send message to dst fd +* Input : u32 fd +* nsfw_mgr_msg* msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_send_msg_socket (u32 fd, nsfw_mgr_msg * msg) +{ + i32 send_len = 0; + i32 off_set = 0; + + if (NULL == msg) + { + NSFW_LOGERR ("msg nul]mgr_fd=%u", fd); + return FALSE; + } + + if (msg->msg_len < sizeof (nsfw_mgr_msg)) + { + msg->msg_len = sizeof (nsfw_mgr_msg); + } + + if (msg->msg_type == MGR_MSG_LARGE_ALARM_RSP) + { + off_set = NSFW_MGR_MSG_HDR_LEN; + } + + /*TODO if closed by peer, may send failed, should close this fd */ + do + { + off_set += send_len; + send_len = + nsfw_base_send (fd, (char *) msg + off_set, msg->msg_len - off_set, + MSG_NOSIGNAL); + if (send_len <= 0) + { + NSFW_LOGERR + ("send error]mgr_fd=%u,send_len=%d,off_set=%d,errno=%d" MSGINFO, + fd, send_len, off_set, errno, PRTMSG (msg)); + return FALSE; + } + } + while ((send_len + off_set) < (i32) msg->msg_len); + NSFW_LOGDBG ("send mgr_msg suc]mgr_fd=%u," MSGINFO, fd, PRTMSG (msg)); + g_mgr_stat.msg_send[msg->msg_type]++; + return TRUE; +} + +#define MAX_RECV_COUNT 100 + +/***************************************************************************** +* Prototype : nsfw_mgr_recv_msg_socket +* Description : receive new message from fd +* Input : u32 fd +* nsfw_mgr_msg* msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_recv_msg_socket (u32 fd, nsfw_mgr_msg * msg, + nsfw_mgr_msg ** large_msg) +{ + i32 recv_len = 0; + i32 off_set = 0; + u32 msg_len = 0; + i32 max_count = 0; + if (NULL == msg) + { + return FALSE; + } + + u8 from_flag = msg->from_mem; + msg_len = msg->msg_len; + do + { + off_set += recv_len; + recv_len = + nsfw_base_recv (fd, (char *) msg + off_set, msg_len - off_set, 0); + if (recv_len <= 0) + { + if ((EINTR == errno || EAGAIN == errno) + && (max_count < MAX_RECV_COUNT)) + { + recv_len = 0; + max_count++; + continue; + } + + NSFW_LOGERR + ("recv error]mgr_fd=%u,recv_len=%d,off_set=%d,errno=%d," + MSGINFO, fd, recv_len, off_set, errno, PRTMSG (msg)); + msg->from_mem = from_flag; + return FALSE; + } + } + while (recv_len + off_set < (i32) msg_len); + + msg->from_mem = from_flag; + + g_mgr_stat.msg_recv[msg->msg_type]++; + + if (msg->msg_len <= msg_len) + { + NSFW_LOGDBG ("recv mgr_msg suc]mgr_fd=%u," MSGINFO, fd, PRTMSG (msg)); + return TRUE; + } + + if (large_msg == NULL) + { + return TRUE; + } + + nsfw_mgr_msg *l_msg = + nsfw_mgr_msg_alloc (msg->msg_type, msg->dst_proc_type); + if (NULL == l_msg) + { + return TRUE; + } + + if (l_msg->msg_len <= msg_len) + { + NSFW_LOGWAR ("alloc new msg error!]len=%u,org_len=%u,type=%u", + l_msg->msg_len, msg->msg_len, msg->msg_type); + nsfw_mgr_msg_free (l_msg); + return TRUE; + } + + max_count = 0; + (void) nsfw_set_sock_block (fd, FALSE); + from_flag = l_msg->from_mem; + u32 l_msg_len = l_msg->msg_len; + do + { + off_set += recv_len; + recv_len = + nsfw_base_recv (fd, (char *) l_msg + off_set, l_msg_len - off_set, 0); + if (recv_len <= 0) + { + if ((EINTR == errno || EAGAIN == errno) + && (max_count < MAX_RECV_COUNT)) + { + recv_len = 0; + max_count++; + continue; + } + + NSFW_LOGERR + ("recv error]mgr_fd=%u,recv_len=%d,off_set=%d,errno=%d," + MSGINFO, fd, recv_len, off_set, errno, PRTMSG (msg)); + l_msg->from_mem = from_flag; + nsfw_mgr_msg_free (l_msg); + return FALSE; + } + } + while (recv_len + off_set < (i32) l_msg_len); + (void) nsfw_set_sock_block (fd, TRUE); + int retVal = MEMCPY_S (l_msg, msg_len, msg, msg_len); + if (EOK != retVal) + { + NSFW_LOGERR ("MEMCPY_S failed] ret=%d", retVal); + l_msg->from_mem = from_flag; + nsfw_mgr_msg_free (l_msg); + return TRUE; + } + l_msg->from_mem = from_flag; + l_msg->msg_len = l_msg_len; + + *large_msg = l_msg; + NSFW_LOGDBG ("recv large mgr_msg suc]mgr_fd=%u," MSGINFO, fd, + PRTMSG (l_msg)); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_send_req_wait_rsp +* Description : send request message and block waiting for it's response + within MGR_COM_RECV_TIMEOUT +* Input : nsfw_mgr_msg* req_msg +* nsfw_mgr_msg* rsp_msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_send_req_wait_rsp (nsfw_mgr_msg * req_msg, nsfw_mgr_msg * rsp_msg) +{ + if (NULL == req_msg) + { + NSFW_LOGERR ("req msg nul!"); + return FALSE; + } + + i32 dst_socket = + nsfw_mgr_get_dst_socket (req_msg->dst_proc_type, req_msg->dst_pid); + if (dst_socket <= 0) + { + dst_socket = + nsfw_mgr_get_new_socket (req_msg->dst_proc_type, req_msg->dst_pid); + if (dst_socket <= 0) + { + NSFW_LOGERR ("send msg get dst_socket_error]" MSGINFO, + PRTMSG (req_msg)); + return FALSE; + } + } + + if ((NULL == rsp_msg) && (req_msg->msg_len == sizeof (nsfw_mgr_msg))) + { + LOCK_MGR_FD (dst_socket) + if (FALSE == nsfw_mgr_send_msg_socket (dst_socket, req_msg)) + { + NSFW_LOGERR ("send msg error]" MSGINFO, PRTMSG (req_msg)); + g_mgr_stat.msg_send_failed++; + UNLOCK_MGR_FD (dst_socket) return FALSE; + } + UNLOCK_MGR_FD (dst_socket) return TRUE; + } + + LOCK_MGR_FD (dst_socket); + (void) nsfw_mgr_unreg_sock_fun (dst_socket); + if (FALSE == nsfw_mgr_send_msg_socket (dst_socket, req_msg)) + { + NSFW_LOGERR ("send msg error]" MSGINFO, PRTMSG (req_msg)); + g_mgr_stat.msg_send_failed++; + (void) nsfw_mgr_reg_sock_fun (dst_socket, nsfw_mgr_new_msg); + UNLOCK_MGR_FD (dst_socket); + return FALSE; + } + + if (NULL == rsp_msg) + { + (void) nsfw_mgr_reg_sock_fun (dst_socket, nsfw_mgr_new_msg); + UNLOCK_MGR_FD (dst_socket) return TRUE; + } + + u16 i; + for (i = 0; i < MGR_COM_MAX_DROP_MSG; i++) + { + if (FALSE == nsfw_mgr_recv_msg_socket (dst_socket, rsp_msg, NULL)) + { + NSFW_LOGERR ("recv msg error]" MSGINFO, PRTMSG (req_msg)); + (void) nsfw_mgr_reg_sock_fun (dst_socket, nsfw_mgr_new_msg); + UNLOCK_MGR_FD (dst_socket) return FALSE; + } + + if ((rsp_msg->seq == req_msg->seq) + && (rsp_msg->msg_type == req_msg->msg_type + MGR_MSG_RSP_BASE)) + { + break; + } + + NSFW_LOGINF ("recv msg forward]" MSGINFO, PRTMSG (rsp_msg)); + rsp_msg->fw_flag = TRUE; + (void) nsfw_mgr_send_msg (rsp_msg); + } + + (void) nsfw_mgr_reg_sock_fun (dst_socket, nsfw_mgr_new_msg); + if (0 == req_msg->dst_pid) + { + (void) nsfw_mgr_new_socket (dst_socket, rsp_msg->src_proc_type, + rsp_msg->src_pid); + } + UNLOCK_MGR_FD (dst_socket) return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_send_msg +* Description : send message to peer +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_send_msg (nsfw_mgr_msg * msg) +{ + return nsfw_mgr_send_req_wait_rsp (msg, NULL); +} + +/***************************************************************************** +* Prototype : nsfw_mgr_msg_in +* Description : when new domain socket mgr message receive, this function will be call +* Input : i32 fd +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_msg_in (i32 fd) +{ + u32 i = 0; + u8 ret = FALSE; + u8 msg_match = FALSE; + nsfw_mgr_msg *msg = nsfw_mgr_null_rspmsg_alloc (); + nsfw_mgr_msg *large_msg = NULL; + + LOCK_MGR_FD (fd) ret = nsfw_mgr_recv_msg_socket (fd, msg, &large_msg); + UNLOCK_MGR_FD (fd) if (large_msg != NULL) + { + nsfw_mgr_msg_free (msg); + msg = large_msg; + } + + if (FALSE == ret) + { + nsfw_mgr_msg_free (msg); + return FALSE; + } + nstack_get_tracing_contex (msg->traceid, 0, 0, -1); + if (msg->fw_flag != TRUE) + { + (void) nsfw_mgr_new_socket (fd, msg->src_proc_type, msg->src_pid); + } + + if (msg->msg_type < MGR_MSG_MAX) + { + for (i = 0; i < NSFW_MGRCOM_MAX_PROC_FUN; i++) + { + if (NULL == g_mgr_fun[msg->msg_type][i]) + { + break; + } + + (void) g_mgr_fun[msg->msg_type][i] (msg); + msg_match = TRUE; + } + } + + if (FALSE != msg_match) + { + nsfw_mgr_msg_free (msg); + nstack_clear_tracing_contex (); + return TRUE; + } + + if (msg->msg_type < MGR_MSG_RSP_BASE) + { + NSFW_LOGERR ("msg match failed! auto rsp]" MSGINFO, PRTMSG (msg)); + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL != rsp_msg) + { + rsp_msg->resp_code = NSFW_MGR_MSG_TYPE_ERROR; + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + } + } + + NSFW_LOGERR ("drop msg]" MSGINFO, PRTMSG (msg)); + /* fix "Out-of-bounds write" type codedex issue */ + if (msg->msg_type < MGR_MSG_MAX) + { + g_mgr_stat.recv_drop[msg->msg_type]++; + } + nsfw_mgr_msg_free (msg); + nstack_clear_tracing_contex (); + return FALSE; + +} + +/***************************************************************************** +* Prototype : nsfw_mgr_new_msg +* Description : when new mgr message recive from socket, this funciton + will call back +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_new_msg (i32 epfd, i32 fd, u32 events) +{ + lint_lock_1 (); + if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN))) + { + (void) nsfw_mgr_del_socket (fd); + (void) nsfw_mgr_unreg_sock_fun (fd); + (void) nsfw_base_close (fd); + lint_unlock_1 (); + return TRUE; + } + + (void) nsfw_mgr_msg_in (fd); + lint_unlock_1 (); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_rereg_fun +* Description : rereg the error socket +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_com_rereg_fun (u32 timer_type, void *data) +{ + (void) nsfw_mgr_reg_sock_fun (timer_type, (nsfw_mgr_sock_fun) data); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_socket_error +* Description : remove the error fd from ep +* Input : i32 fd +* nsfw_mgr_sock_fun fun +* i32 timer +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_com_socket_error (i32 fd, nsfw_mgr_sock_fun fun, i32 timer) +{ + struct timespec time_left = { timer, 0 }; + nsfw_mgr_unreg_sock_fun (fd); + nsfw_timer_reg_timer (fd, (void *) fun, nsfw_mgr_com_rereg_fun, time_left); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_new_connection +* Description : when new mgr connection in, this funciton will call back +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_new_connection (i32 epfd, i32 fd, u32 events) +{ + if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN))) + { + (void) nsfw_base_close (fd); + NSFW_LOGWAR ("listen disconnect!]epfd=%d,listen=%d,event=0x%x", epfd, + fd, events); + (void) nsfw_mgr_unreg_sock_fun (fd); + i32 listen_fd = nsfw_mgr_get_listen_socket (); + if (listen_fd < 0) + { + NSFW_LOGERR + ("get listen_fd faied!]epfd=%d,listen_fd=%d,event=0x%x", epfd, + fd, events); + return FALSE; + } + + (void) nsfw_mgr_reg_sock_fun (listen_fd, nsfw_mgr_new_connection); + return TRUE; + } + + struct sockaddr in_addr; + socklen_t in_len; + int infd; + in_len = sizeof in_addr; + + int size, size_len; + u8 accept_flag = FALSE; + while (1) + { + infd = nsfw_base_accept (fd, &in_addr, &in_len); + if (infd == -1) + { + if (FALSE == accept_flag) + { + nsfw_mgr_com_socket_error (fd, nsfw_mgr_new_connection, 1); + } + break; + } + + if (-1 == nsfw_set_close_on_exec (infd)) + { + (void) nsfw_base_close (infd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", infd, errno); + break; + } + + size = MAX_RECV_BUF_DEF; + size_len = sizeof (size); + if (0 > + nsfw_base_setsockopt (infd, SOL_SOCKET, SO_RCVBUF, (void *) &size, + (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + if (0 > + nsfw_base_setsockopt (infd, SOL_SOCKET, SO_SNDBUF, (void *) &size, + (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + (void) nsfw_mgr_reg_sock_fun (infd, nsfw_mgr_new_msg); + NSFW_LOGDBG ("accept_flag new fd]new_mgr_fd=%d", infd); + accept_flag = TRUE; + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_set_sock_block +* Description : set fd blok or not for epoll thread +* Input : i32 sock +* u8 flag +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_set_sock_block (i32 sock, u8 flag) +{ + i32 flags; + flags = nsfw_base_fcntl (sock, F_GETFL, 0); + if (flags < 0) + { + NSFW_LOGERR ("fcntl err]new_mgr_fd=%d,errno=%d", sock, errno); + return -1; + } + + if (TRUE == flag) + { + flags = flags | O_NONBLOCK; + } + else + { + flags = flags & (~O_NONBLOCK); + struct timeval tv; + tv.tv_sec = MGR_COM_RECV_TIMEOUT; + tv.tv_usec = 0; + if (nsfw_base_setsockopt + (sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof tv)) + { + NSFW_LOGERR ("setsockopt socket err]mgr_fd=%d", sock); + return -1; + } + } + + if (nsfw_base_fcntl (sock, F_SETFL, flags) < 0) + { + NSFW_LOGERR ("fcntl err]new_mgr_fd=%d,errno=%d,flags=%d", sock, errno, + flags); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_set_close_on_exec +* Description : close on exec set +* Input : i32 sock +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_set_close_on_exec (i32 sock) +{ + i32 flags; + flags = nsfw_base_fcntl (sock, F_GETFD, 0); + if (flags < 0) + { + NSFW_LOGERR ("fcntl err]fd=%d,errno=%d", sock, errno); + return -1; + } + + flags |= FD_CLOEXEC; + + if (nsfw_base_fcntl (sock, F_SETFD, flags) < 0) + { + NSFW_LOGERR ("fcntl err]fd=%d,errno=%d,flags=%d", sock, errno, flags); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_add_sock_to_ep +* Description : add fd to epoll wait thread +* Input : i32 fd +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_add_sock_to_ep (i32 fd) +{ + struct epoll_event event; + event.data.fd = fd; + event.events = EPOLLIN; + if (g_ep_proc.epfd == 0) + { + return TRUE; + } + + (void) nsfw_set_sock_block (fd, TRUE); + + if (0 > nsfw_base_epoll_ctl (g_ep_proc.epfd, EPOLL_CTL_ADD, fd, &event)) + { + NSFW_LOGINF + ("add sock to ep thread failed]mgr_fd=%d,errno=%d,epfd=%d", fd, + errno, g_ep_proc.epfd); + return FALSE; + } + + NSFW_LOGDBG ("add sock to ep thread]mgr_fd=%d,epfd=%d", fd, + g_ep_proc.epfd) return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_rmv_sock_from_ep +* Description : remove fd from epoll thread +* Input : i32 fd +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_rmv_sock_from_ep (i32 fd) +{ + struct epoll_event event; + event.data.fd = fd; + event.events = EPOLLIN; + if (g_ep_proc.epfd == 0) + { + return TRUE; + } + + (void) nsfw_set_sock_block (fd, FALSE); + + if (0 > nsfw_base_epoll_ctl (g_ep_proc.epfd, EPOLL_CTL_DEL, fd, &event)) + { + NSFW_LOGINF + ("rmv sock to ep thread failed] mgr_fd=%d,errno=%d,epfd=%d", fd, + errno, g_ep_proc.epfd); + return FALSE; + } + + NSFW_LOGDBG ("rmv sock to ep thread] mgr_fd=%d,epfd=%d", fd, + g_ep_proc.epfd) return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_reg_sock_fun +* Description : reg fd process function to call back when epoll thread + recvice new event of the reg fd +* Input : i32 fd +* nsfw_mgr_sock_fun fun +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_reg_sock_fun (i32 fd, nsfw_mgr_sock_fun fun) +{ + lint_lock_1 (); + if ((fd >= (i32) NSFW_MGR_FD_MAX) || (fd < 0) || NULL == fun) + { + NSFW_LOGINF ("reg sock fun error!] mgr_fd=%d,fun=%p", fd, fun); + lint_unlock_1 (); + return FALSE; + } + + if ((g_ep_proc.ep_fun) && (NULL == g_ep_proc.ep_fun[fd])) + { + g_ep_proc.ep_fun[fd] = fun; + if (FALSE == nsfw_add_sock_to_ep (fd)) + { + g_ep_proc.ep_fun[fd] = NULL; + lint_unlock_1 (); + return FALSE; + } + + NSFW_LOGDBG ("reg sock fun] mgr_fd=%d,fun=%p", fd, fun); + lint_unlock_1 (); + return TRUE; + } + lint_unlock_1 (); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_unreg_sock_fun +* Description : unreg the fd event function +* Input : i32 fd +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_mgr_unreg_sock_fun (i32 fd) +{ + lint_lock_1 (); + if (fd >= (i32) NSFW_MGR_FD_MAX) + { + NSFW_LOGINF ("unreg sock fun failed!] mgr_fd=%d", fd); + lint_unlock_1 (); + return; + } + + if ((g_ep_proc.ep_fun) && (NULL != g_ep_proc.ep_fun[fd])) + { + g_ep_proc.ep_fun[fd] = NULL; + (void) nsfw_rmv_sock_from_ep (fd); + NSFW_LOGDBG ("unreg sock fun] mgr_fd=%d", fd); + lint_unlock_1 (); + return; + } + + lint_unlock_1 (); + return; +} + +/***************************************************************************** +* Prototype : nsfw_sock_fun_callback +* Description : call back the event process function +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : static inline u8 +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC inline u8 +nsfw_sock_fun_callback (i32 epfd, i32 fd, u32 events) +{ + if ((fd < (i32) NSFW_MGR_FD_MAX) + && (g_ep_proc.ep_fun) && (NULL != g_ep_proc.ep_fun[fd])) + { + (void) g_ep_proc.ep_fun[fd] (epfd, fd, events); + return TRUE; + } + + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_sock_add_to_ep +* Description : add all event process function has ben reg to the epoll + thread when thread start +* Input : i32 epfd +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_sock_add_to_ep (i32 epfd) +{ + u32 i; + + for (i = 0; i < NSFW_MGR_FD_MAX; i++) + { + if ((g_ep_proc.ep_fun) && (NULL == g_ep_proc.ep_fun[i])) + { + continue; + } + (void) nsfw_add_sock_to_ep (i); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_start +* Description : start mgr com module +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_com_start () +{ + i32 listern_fd = nsfw_mgr_get_listen_socket (); + if (listern_fd < 0) + { + NSFW_LOGERR ("get listern_fd failed!"); + return FALSE; + } + + NSFW_LOGINF ("start mgr_com module!] listern_fd=%d", listern_fd); + (void) nsfw_mgr_reg_sock_fun (listern_fd, nsfw_mgr_new_connection); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_start_local +* Description : start_local_msg_com +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_com_start_local (u8 proc_type) +{ + int fd[2]; + if ((socketpair (AF_UNIX, SOCK_STREAM, 0, fd)) < 0) + { + NSFW_LOGERR ("create socket err] type=%u,errno=%d", proc_type, errno); + return FALSE; + } + + (void) nsfw_mgr_new_socket (fd[0], proc_type, get_sys_pid ()); + (void) nsfw_mgr_new_socket (fd[1], proc_type, get_sys_pid ()); + (void) nsfw_mgr_reg_sock_fun (fd[0], nsfw_mgr_new_msg); + (void) nsfw_mgr_reg_sock_fun (fd[1], nsfw_mgr_new_msg); + NSFW_LOGINF ("create local socket] fd0=%d,fd1=%d", fd[0], fd[1]); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_listen_thread +* Description : epoll thread function +* Input : void* arg +* Output : None +* Return Value : void * +* Calls : +* Called By : +*****************************************************************************/ +void * +nsfw_mgr_listen_thread (void *arg) +{ + i32 epfd = 0; + //i32 listen_socket = 0; + + lint_lock_1 (); +#define MAXEVENTS 10 + epfd = nsfw_base_epoll_create (10); + + struct epoll_event events[MAXEVENTS]; + if (EOK != MEMSET_S (events, sizeof (events), 0, sizeof (events))) + { + NSFW_LOGERR ("MEMSET_S failed!]epfd=%d", epfd); + lint_unlock_1 (); + return NULL; + } + + g_ep_proc.epfd = epfd; + g_ep_proc.hbt_count = 0; + (void) nsfw_sock_add_to_ep (epfd); + lint_unlock_1 (); + while (1) + { + lint_lock_1 (); + int n, i; + n = nsfw_base_epoll_wait (epfd, events, MAXEVENTS, -1); + for (i = 0; i < n; i++) + { + if (TRUE == + nsfw_sock_fun_callback (epfd, events[i].data.fd, + events[i].events)) + { + g_ep_proc.hbt_count = 0; + continue; + } + + NSFW_LOGERR ("error event recv] fd=%d,event=%d", + events[i].data.fd, events[i].events); + } + lint_unlock_1 (); + } + +} + +NSTACK_STATIC inline void +get_thread_policy (pthread_attr_t * attr) +{ + int policy; + int rs = pthread_attr_getschedpolicy (attr, &policy); + if (rs != 0) + { + NSFW_LOGERR ("pthread_attr_getschedpolicy failed"); + return; + } + switch (policy) + { + case SCHED_FIFO: + NSFW_LOGINF ("policy= SCHED_FIFO"); + break; + case SCHED_RR: + NSFW_LOGINF ("policy= SCHED_RR"); + break; + case SCHED_OTHER: + NSFW_LOGINF ("policy=SCHED_OTHER"); + break; + default: + NSFW_LOGINF ("policy=UNKNOWN"); + break; + } + + return; +} + +NSTACK_STATIC inline void +get_thread_priority (pthread_attr_t * attr) +{ + struct sched_param param; + int rs = pthread_attr_getschedparam (attr, ¶m); + if (rs != 0) + { + NSFW_LOGERR ("pthread_attr_getschedparam failed"); + return; + } + + NSFW_LOGINF ("get thread priority] pri=%d", param.sched_priority); +} + +/* support thread priority configuration */ +void +set_thread_attr (pthread_attr_t * pattr, int stacksize, int pri, int policy) +{ + struct sched_param param; + (void) pthread_attr_init (pattr); + + if (stacksize > 0) + { + (void) pthread_attr_setstacksize (pattr, stacksize); + } + + param.sched_priority = pri; + if (SCHED_OTHER != policy) + { + (void) pthread_attr_setschedpolicy (pattr, policy); + (void) pthread_attr_setschedparam (pattr, ¶m); + (void) pthread_attr_setinheritsched (pattr, PTHREAD_EXPLICIT_SCHED); + } + get_thread_policy (pattr); + get_thread_priority (pattr); +} + +/***************************************************************************** +* Prototype : nsfw_mgr_ep_start +* Description : start epoll thread +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_ep_start () +{ + /* heart beat thread should have the same priority with the tcpip thread */ + pthread_attr_t attr; + pthread_attr_t *pattr = NULL; + + if (g_thread_policy != SCHED_OTHER) + { + set_thread_attr (&attr, 0, g_thread_pri, g_thread_policy); + pattr = &attr; + } + + if (pthread_create + (&g_ep_proc.ep_thread, pattr, nsfw_mgr_listen_thread, NULL)) + { + return FALSE; + } + + NSFW_LOGINF ("start thread] id=%d", g_ep_proc.ep_thread); + + if (pthread_setname_np (g_ep_proc.ep_thread, NSFW_MGRCOM_THREAD)) + { + return TRUE; + } + (void) nsfw_reg_trace_thread (g_ep_proc.ep_thread); + return TRUE; +} + +int +nsfw_mgr_com_chk_hbt (int v_add) +{ + int ret = g_ep_proc.hbt_count; + g_ep_proc.hbt_count += v_add; + return ret; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_comm_fd_destroy +* Description : free the memeory +* Input : +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_mgr_comm_fd_destroy () +{ + if (g_ep_proc.ep_fun) + { + free (g_ep_proc.ep_fun); + g_ep_proc.ep_fun = NULL; + } + if (g_mgr_sockt_map.sock) + { + free (g_mgr_sockt_map.sock); + g_mgr_sockt_map.sock = NULL; + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_comm_fd_init +* Description : fd map and socket info init +* Input : u32 proc_type +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_comm_fd_init (u32 proc_type) +{ + /*only app need to do this */ + if ((g_mgr_sockt_map.sock) && (g_ep_proc.ep_fun)) + { + return 0; + } + if (NSFW_PROC_APP == proc_type) + { + long sysfdmax = 0; + sysfdmax = sysconf (_SC_OPEN_MAX); + NSFW_LOGINF ("] sys max open files=%d", sysfdmax); + if (sysfdmax > 0) + { + NSFW_MGR_FD_MAX = + (int) ((sysfdmax <= + NSFW_MGRCOM_MAX_SOCKET * + 60) ? sysfdmax : NSFW_MGRCOM_MAX_SOCKET * 60); + } + else + { + NSFW_LOGERR ("get sys max open file fail"); + NSFW_MGR_FD_MAX = NSFW_MGRCOM_MAX_SOCKET; + } + } + NSFW_LOGINF ("] final max fd=%d", NSFW_MGR_FD_MAX); + if (!g_mgr_sockt_map.sock) + { + g_mgr_sockt_map.sock = + (nsfw_mgr_sock_info *) malloc (sizeof (nsfw_mgr_sock_info) * + NSFW_MGR_FD_MAX); + if (NULL == g_mgr_sockt_map.sock) + { + NSFW_LOGERR ("malloc fail] length=%d", + sizeof (nsfw_mgr_sock_info) * NSFW_MGR_FD_MAX); + return -1; + } + (void) MEMSET_S (g_mgr_sockt_map.sock, + sizeof (nsfw_mgr_sock_info) * NSFW_MGR_FD_MAX, 0, + sizeof (nsfw_mgr_sock_info) * NSFW_MGR_FD_MAX); + } + if (!g_ep_proc.ep_fun) + { + g_ep_proc.ep_fun = + (nsfw_mgr_sock_fun *) malloc (sizeof (nsfw_mgr_sock_fun) * + NSFW_MGR_FD_MAX); + if (NULL == g_ep_proc.ep_fun) + { + NSFW_LOGERR ("malloc fail] length=%d ", + sizeof (nsfw_mgr_sock_fun) * NSFW_MGR_FD_MAX); + return -1; + } + (void) MEMSET_S (g_ep_proc.ep_fun, + sizeof (nsfw_mgr_sock_fun) * NSFW_MGR_FD_MAX, 0, + sizeof (nsfw_mgr_sock_fun) * NSFW_MGR_FD_MAX); + } + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int nsfw_mgr_com_module_init (void *param); +int +nsfw_mgr_com_module_init (void *param) +{ + lint_lock_1 (); + u32 proc_type = (u32) ((long long) param); + nsfw_mgr_init_cfg *mgr_cfg = &g_mgr_com_cfg; + const char *directory = NSFW_DOMAIN_DIR; + const char *home_dir = getenv ("HOME"); + + NSFW_LOGINF ("module mgr init] type=%u", proc_type); + + if (getuid () != 0 && home_dir != NULL) + directory = home_dir; + + if (0 != nsfw_mgr_comm_fd_init (proc_type)) + { + NSFW_LOGERR ("fd init fail] proc_type=%u", proc_type); + lint_unlock_1 (); + return -1; + } + + switch (proc_type) + { + case NSFW_PROC_MAIN: + /* modify destMax, remove "-1" */ + if (EOK != + STRCPY_S (mgr_cfg->domain_path, NSFW_MGRCOM_PATH_LEN, directory)) + { + NSFW_LOGERR ("module mgr init STRCPY_S failed!"); + lint_unlock_1 (); + return -1; + } + + /* modify destMax, remove "-1" */ + if (EOK != + STRCAT_S (mgr_cfg->domain_path, NSFW_MGRCOM_PATH_LEN, + NSFW_MAIN_FILE)) + { + NSFW_LOGERR ("module mgr init STRCAT_S failed!"); + lint_unlock_1 (); + return -1; + } + + NSFW_LOGINF ("module mgr init]NSFW_PROC_MAIN domain_path=%s", + mgr_cfg->domain_path); + + if (TRUE != nsfw_mgr_com_start ()) + { + NSFW_LOGERR ("module mgr nsfw_mgr_com_start failed!"); + lint_unlock_1 (); + return -1; + } + + break; + case NSFW_PROC_MASTER: + /* modify destMax, remove "-1" */ + if (EOK != + STRCPY_S (mgr_cfg->domain_path, NSFW_MGRCOM_PATH_LEN, directory)) + { + NSFW_LOGERR ("module mgr init STRCPY_S failed!"); + lint_unlock_1 (); + return -1; + } + + /* modify destMax, remove "-1" */ + if (EOK != + STRCAT_S (mgr_cfg->domain_path, NSFW_MGRCOM_PATH_LEN, + NSFW_MASTER_FILE)) + { + NSFW_LOGERR ("module mgr init STRCAT_S failed!"); + lint_unlock_1 (); + return -1; + } + + NSFW_LOGINF ("module mgr init]NSFW_PROC_MASTER domain_path=%s", + mgr_cfg->domain_path); + + if (TRUE != nsfw_mgr_com_start ()) + { + NSFW_LOGERR ("module mgr nsfw_mgr_com_start failed!"); + lint_unlock_1 (); + return -1; + } + + break; + case NSFW_PROC_TOOLS: + break; + case NSFW_PROC_CTRL: + if (TRUE != nsfw_mgr_com_start_local (proc_type)) + { + NSFW_LOGERR ("module mgr nsfw_mgr_com_start_local failed!"); + lint_unlock_1 (); + return -1; + } + break; + default: + if (proc_type < NSFW_PROC_MAX) + { + break; + } + lint_unlock_1 (); + return -1; + } + + mgr_cfg->msg_size = MGR_COM_MSG_COUNT_DEF; + mgr_cfg->max_recv_timeout = MGR_COM_RECV_TIMEOUT_DEF; + mgr_cfg->max_recv_drop_msg = MGR_COM_MAX_DROP_MSG_DEF; + + mgr_cfg->proc_type = proc_type; + + nsfw_mem_sppool pmpinfo; + if (EOK != MEMSET_S (&pmpinfo, sizeof (pmpinfo), 0, sizeof (pmpinfo))) + { + NSFW_LOGERR ("Error to memset!!!"); + nsfw_mgr_comm_fd_destroy (); + lint_unlock_1 (); + return -1; + } + + pmpinfo.enmptype = NSFW_MRING_MPMC; + pmpinfo.usnum = mgr_cfg->msg_size; + pmpinfo.useltsize = sizeof (nsfw_mgr_msg); + pmpinfo.isocket_id = NSFW_SOCKET_ANY; + pmpinfo.stname.entype = NSFW_NSHMEM; + if (-1 == + SPRINTF_S (pmpinfo.stname.aname, sizeof (pmpinfo.stname.aname), "%s", + "MS_MGR_MSGPOOL")) + { + NSFW_LOGERR ("Error to SPRINTF_S!!!"); + nsfw_mgr_comm_fd_destroy (); + lint_unlock_1 (); + return -1; + } + + mgr_cfg->msg_pool = nsfw_mem_sp_create (&pmpinfo); + + if (!mgr_cfg->msg_pool) + { + NSFW_LOGERR ("module mgr init msg_pool alloc failed!"); + nsfw_mgr_comm_fd_destroy (); + lint_unlock_1 (); + return -1; + } + + (void) MEM_STAT (NSFW_MGR_COM_MODULE, pmpinfo.stname.aname, NSFW_NSHMEM, + nsfw_mem_get_len (mgr_cfg->msg_pool, NSFW_MEM_SPOOL)); + + if ((NSFW_PROC_TOOLS == proc_type) + || (NSFW_PROC_CTRL == proc_type) || (NSFW_PROC_MAIN == proc_type)) + { + if (TRUE != nsfw_mgr_ep_start ()) + { + NSFW_LOGERR ("module mgr nsfw_mgr_ep_start failed!"); + nsfw_mgr_comm_fd_destroy (); + lint_unlock_1 (); + return -1; + } + } + lint_unlock_1 (); + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_run_script +* Description : run a linux shell script +* Input : const char *cmd, char *result, int result_buf_len +* Output : result length +* Return Value : int +* Calls : +* Called By : + *****************************************************************************/ +int +nsfw_mgr_run_script (const char *cmd, char *result, int result_buf_len) +{ + if (!cmd || !result || result_buf_len <= 1) + { + return -1; + } + + FILE *fp = popen (cmd, "r"); + if (fp != NULL) + { + size_t n = fread (result, sizeof (char), result_buf_len - 1, fp); + if (n == 0) + { + result[0] = '\0'; + } + else if ('\n' == result[n - 1]) + { + result[n - 1] = '\0'; + } + else + { + result[n] = '\0'; + } + + pclose (fp); + return n; + } + + return -1; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME(NSFW_MGR_COM_MODULE) +NSFW_MODULE_PRIORITY(10) +NSFW_MODULE_DEPENDS(NSFW_MEM_MGR_MODULE) +NSFW_MODULE_INIT(nsfw_mgr_com_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/mgr_com/mgr_com.h b/src/framework/ipc/mgr_com/mgr_com.h new file mode 100644 index 0000000..c4333a1 --- /dev/null +++ b/src/framework/ipc/mgr_com/mgr_com.h @@ -0,0 +1,150 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/***************************************************************************** +* Prototype : ifndef _NSFW_MGRCOM_MODULE_H +* Description : mgr com module definition +* Input : None +* Output : None +* Return Value : # +* Calls : +* Called By : + *****************************************************************************/ +#ifndef _NSFW_MGRCOM_MODULE_H +#define _NSFW_MGRCOM_MODULE_H + +#include "pthread.h" +#include "nsfw_mem_api.h" +#include "common_mem_api.h" + +#include "common_func.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_MGRCOM_PATH_LEN 128 +#define NSFW_MGRCOM_MAX_SOCKET 1024 +#define NSFW_MGRCOM_MAX_PROC_FUN 8 + +#define MAX_RECV_BUF_DEF 0x34000*2 + +#define MGR_COM_MSG_COUNT_DEF 1023 /*g_mgr_com_cfg */ +#define MGR_COM_RECV_TIMEOUT_DEF 5 +#define MGR_COM_MAX_DROP_MSG_DEF 1024 + +#define MGR_COM_MSG_COUNT (g_mgr_com_cfg.msg_size) +#define MGR_COM_RECV_TIMEOUT (g_mgr_com_cfg.max_recv_timeout) +#define MGR_COM_MAX_DROP_MSG (g_mgr_com_cfg.max_recv_drop_msg) + +#define NSFW_MAIN_FILE "/ip_module/nStackMainMgr" +#define NSFW_MASTER_FILE "/ip_module/nStackMasterMgr" +#define NSFW_ALARM_FILE "/HuskyAlarm.domain" + +#define NSFW_MGRCOM_THREAD "nStackMgrCom" + +typedef struct _nsfw_mgr_init_cfg +{ + u8 proc_type; /*fw_poc_type */ + u8 max_recv_timeout; + u16 max_recv_drop_msg; + u32 msg_size; + common_mem_atomic32_t cur_idx; + u64 u64reserve; + mring_handle msg_pool; + char domain_path[NSFW_MGRCOM_PATH_LEN]; +} nsfw_mgr_init_cfg; + +typedef struct _nsfw_mgrcom_stat +{ + u64 msg_send[MGR_MSG_MAX]; + u64 msg_recv[MGR_MSG_MAX]; + u64 recv_drop[MGR_MSG_MAX]; + u64 msg_alloc; + u64 msg_free; + u64 msg_send_failed; + u64 reconnect_count; +} nsfw_mgrcom_stat; + +typedef struct _nsfw_mgr_sock_info +{ + u8 proc_type; /*_ns_poc_type*/ + u32 host_pid; + common_mem_spinlock_t opr_lock; +} nsfw_mgr_sock_info; + +typedef struct _nsfw_mgr_sock_map +{ + i32 proc_cache[NSFW_PROC_MAX]; + nsfw_mgr_sock_info *sock; +} nsfw_mgr_sock_map; + +#define NSFW_SOCK_MAX_PROC_FUN 4 + +typedef struct _nsfw_mgrcom_proc_fun +{ + i32 fd; + nsfw_mgr_sock_fun fun; +} nsfw_mgrcom_proc_fun; + +typedef struct _nsfw_mgrcom_proc +{ + i32 epfd; + u32 hbt_count; + pthread_t ep_thread; + nsfw_mgr_sock_fun *ep_fun; +} nsfw_mgrcom_proc; + +i32 nsfw_set_sock_block (i32 sock, u8 flag); + +u8 nsfw_rmv_sock_from_ep (i32 fd); +u8 nsfw_add_sock_to_ep (i32 fd); + +int nsfw_mgr_new_msg (i32 epfd, i32 socket, u32 events); + +u8 nsfw_mgr_ep_start (); +u8 nsfw_mgr_stop (); + +#define LOCK_MGR_FD(_fd){\ + if ((i32)NSFW_MGR_FD_MAX > _fd)\ + {\ + common_mem_spinlock_lock(&g_mgr_sockt_map.sock[_fd].opr_lock);\ + }\ +} + +#define UNLOCK_MGR_FD(_fd){\ + if ((i32)NSFW_MGR_FD_MAX > _fd)\ + {\ + common_mem_spinlock_unlock(&g_mgr_sockt_map.sock[_fd].opr_lock);\ + }\ +} + +#define NSFW_MGR_FD_MAX g_mgr_sockfdmax + +extern void set_thread_attr (pthread_attr_t * pattr, int stacksize, int pri, + int policy); + +extern void nsfw_com_attr_set (int policy, int pri); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_MGRCOM_MODULE_H */ diff --git a/src/framework/ipc/ps/nsfw_fd_timer.c b/src/framework/ipc/ps/nsfw_fd_timer.c new file mode 100644 index 0000000..57535a3 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_fd_timer.c @@ -0,0 +1,378 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> +#include <sys/timerfd.h> + +#include "types.h" +#include "list.h" + +#include "nstack_securec.h" +#include "nsfw_init.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_mem_api.h" +#include "nstack_log.h" +#include "nsfw_base_linux_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_maintain_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_TIMER_CYCLE 1 +#define NSFW_TIMER_INFO_MAX_COUNT_DEF 8191 +#define NSFW_TIMER_INFO_MAX_COUNT (g_timer_cfg.timer_info_size) +/* *INDENT-OFF* */ +nsfw_timer_init_cfg g_timer_cfg; + +u8 g_hbt_switch = FALSE; +/* *INDENT-ON* */ + +/***************************************************************************** +* Prototype : nsfw_timer_reg_timer +* Description : reg timer with callback function when timeout +* Input : u32 timer_type +* void* data +* nsfw_timer_proc_fun fun +* struct timespec time_left +* Output : None +* Return Value : nsfw_timer_info* +* Calls : +* Called By : +* +*****************************************************************************/ +nsfw_timer_info * +nsfw_timer_reg_timer (u32 timer_type, void *data, + nsfw_timer_proc_fun fun, struct timespec time_left) +{ + nsfw_timer_info *tm_info = NULL; + if (0 == + nsfw_mem_ring_dequeue (g_timer_cfg.timer_info_pool, (void *) &tm_info)) + { + NSFW_LOGERR ("dequeue error]data=%p,fun=%p", data, fun); + return NULL; + } + + if (EOK != MEMSET_S (tm_info, sizeof (*tm_info), 0, sizeof (*tm_info))) + { + if (0 == nsfw_mem_ring_enqueue (g_timer_cfg.timer_info_pool, tm_info)) + { + NSFW_LOGERR ("enqueue error]data=%p,fun=%p", data, fun); + } + NSFW_LOGERR ("mem set error]data=%p,fun=%p", data, fun); + return NULL; + } + + tm_info->fun = fun; + tm_info->argv = data; + tm_info->time_left = time_left; + //tm_info->time_left.tv_sec += NSFW_TIMER_CYCLE; + tm_info->timer_type = timer_type; + list_add_tail (&tm_info->node, &g_timer_cfg.timer_head); + tm_info->alloc_flag = TRUE; + return tm_info; +} + +/***************************************************************************** +* Prototype : nsfw_timer_rmv_timer +* Description : stop timer +* Input : nsfw_timer_info* tm_info +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void +nsfw_timer_rmv_timer (nsfw_timer_info * tm_info) +{ + if (NULL == tm_info) + { + NSFW_LOGWAR ("tm_info nul"); + return; + } + + if (FALSE == tm_info->alloc_flag) + { + NSFW_LOGERR ("tm_info refree]tm_info=%p,argv=%p,fun=%p", tm_info, + tm_info->argv, tm_info->fun); + return; + } + + tm_info->alloc_flag = FALSE; + list_del (&tm_info->node); + if (0 == nsfw_mem_ring_enqueue (g_timer_cfg.timer_info_pool, tm_info)) + { + NSFW_LOGERR ("tm_info free failed]tm_info=%p,argv=%p,fun=%p", tm_info, + tm_info->argv, tm_info->fun); + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_timer_exp +* Description : timer expire +* Input : u64 count +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +void +nsfw_timer_exp (u64 count) +{ + nsfw_timer_info *tm_info = NULL; + struct list_head *tNode; + struct list_head *tPretNode; + + LINT_LIST ()list_for_each_entry (tm_info, tNode, (&g_timer_cfg.timer_head), + node) + { + tPretNode = tm_info->node.prev; + if (tm_info->time_left.tv_sec > (long) count * NSFW_TIMER_CYCLE) + { + tm_info->time_left.tv_sec -= count * NSFW_TIMER_CYCLE; + continue; + } + + list_del (&tm_info->node); + list_add_tail (&tm_info->node, &g_timer_cfg.exp_timer_head); + tNode = tPretNode; + } + + u32 i = 0; + while (!list_empty (&g_timer_cfg.exp_timer_head) + && i++ < NSFW_TIMER_INFO_MAX_COUNT) + { + tm_info = + (nsfw_timer_info *) list_get_first (&g_timer_cfg.exp_timer_head); + if (NULL != tm_info->fun) + { + (void) tm_info->fun (tm_info->timer_type, tm_info->argv); + } + nsfw_timer_rmv_timer (tm_info); + } + +} + +/***************************************************************************** +* Prototype : nsfw_get_timer_socket +* Description : get timer socket from kernel +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_get_timer_socket () +{ + i32 tfd = timerfd_create (CLOCK_MONOTONIC, TFD_NONBLOCK); + if (tfd == -1) + { + NSFW_LOGERR ("timerfd_create failed!]errno=%d\n", errno); + return -1; + } + + /* close on exe */ + if (-1 == nsfw_set_close_on_exec (tfd)) + { + (void) nsfw_base_close (tfd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", tfd, errno); + return -1; + } + + struct itimerspec ts; + ts.it_interval.tv_sec = NSFW_TIMER_CYCLE; + ts.it_interval.tv_nsec = 0; + ts.it_value.tv_sec = 0; + ts.it_value.tv_nsec = NSFW_TIMER_CYCLE; + + if (timerfd_settime (tfd, 0, &ts, NULL) < 0) + { + NSFW_LOGERR ("timerfd_settime failed] errno=%d", errno); + close (tfd); + return -1; + } + + return tfd; +} + +/***************************************************************************** +* Prototype : nsfw_timer_notify_fun +* Description : receive timer event from kernel +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_timer_notify_fun (i32 epfd, i32 fd, u32 events) +{ + i32 rc; + + if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN))) + { + (void) nsfw_base_close (fd); + NSFW_LOGWAR ("timer disconnect!]epfd=%d,timer=%d,event=0x%x", epfd, + fd, events); + + (void) nsfw_mgr_unreg_sock_fun (fd); + i32 timer_fd = nsfw_get_timer_socket (); + if (timer_fd < 0) + { + NSFW_LOGERR ("get timer_fd faied!]epfd=%d,timer_fd=%d,event=0x%x", + epfd, fd, events); + return FALSE; + } + + (void) nsfw_mgr_reg_sock_fun (timer_fd, nsfw_timer_notify_fun); + return TRUE; + } + + u64 data; + while (1) + { + rc = nsfw_base_read (fd, &data, sizeof (data)); + if (rc == 0) + { + NSFW_LOGERR ("timer_fd recv 0]timer_fd=%d,errno=%d", fd, errno); + break; + } + else if (rc == -1) + { + if (errno == EINTR || errno == EAGAIN) + { + break; + } + NSMON_LOGERR ("timer_fd recv]timer_fd=%d,errno=%d", fd, errno); + break; + } + + nsfw_timer_exp (data); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_timer_start +* Description : reg the timer module to epoll thread +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +u8 +nsfw_timer_start () +{ + i32 timer_fd = nsfw_get_timer_socket (); + if (timer_fd < 0) + { + NSFW_LOGERR ("get timer_fd failed!"); + return FALSE; + } + + NSFW_LOGINF ("start timer_fd module!]timer_fd=%d", timer_fd); + (void) nsfw_mgr_reg_sock_fun (timer_fd, nsfw_timer_notify_fun); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_timer_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +nsfw_timer_module_init (void *param) +{ + u32 proc_type = (u32) ((long long) param); + nsfw_timer_init_cfg *timer_cfg = &g_timer_cfg; + NSFW_LOGINF ("ps module init]type=%u", proc_type); + switch (proc_type) + { + case NSFW_PROC_MASTER: + case NSFW_PROC_MAIN: + (void) NSFW_REG_SOFT_INT (NSFW_DBG_MODE_PARAM, g_hbt_switch, 0, 1); + break; + case NSFW_PROC_TOOLS: + case NSFW_PROC_CTRL: + break; + default: + return 0; + } + + timer_cfg->timer_info_size = NSFW_TIMER_INFO_MAX_COUNT_DEF; + + nsfw_mem_sppool pmpinfo; + pmpinfo.enmptype = NSFW_MRING_MPMC; + pmpinfo.usnum = timer_cfg->timer_info_size; + pmpinfo.useltsize = sizeof (nsfw_timer_info); + pmpinfo.isocket_id = NSFW_SOCKET_ANY; + pmpinfo.stname.entype = NSFW_NSHMEM; + if (-1 == + SPRINTF_S (pmpinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + "MS_TM_INFOPOOL")) + { + NSFW_LOGERR ("SPRINTF_S failed"); + return -1; + } + timer_cfg->timer_info_pool = nsfw_mem_sp_create (&pmpinfo); + + if (!timer_cfg->timer_info_pool) + { + NSFW_LOGERR ("alloc timer info pool_err"); + return -1; + } + + MEM_STAT (NSFW_TIMER_MODULE, pmpinfo.stname.aname, NSFW_NSHMEM, + nsfw_mem_get_len (timer_cfg->timer_info_pool, NSFW_MEM_SPOOL)); + + INIT_LIST_HEAD (&(timer_cfg->timer_head)); + INIT_LIST_HEAD (&(timer_cfg->exp_timer_head)); + + (void) nsfw_timer_start (); + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_TIMER_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_MGR_COM_MODULE) +NSFW_MODULE_INIT (nsfw_timer_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/ps/nsfw_ps_mem_module.c b/src/framework/ipc/ps/nsfw_ps_mem_module.c new file mode 100644 index 0000000..9cda6b3 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_ps_mem_module.c @@ -0,0 +1,924 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nsfw_ps_module.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_ps_mem_api.h" +#include "nsfw_ps_mem_module.h" +#include "nsfw_ps_api.h" +#include "nsfw_maintain_api.h" +#include "nsfw_fd_timer_api.h" + +#include "nstack_log.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +ns_mem_mng_init_cfg g_mem_cfg; + +int mem_ps_exiting (void *pps_info, void *argv); + +int +nsfw_mem_ps_exit_resend_timeout (u32 timer_type, void *data) +{ + nsfw_ps_info *ps_info = data; + if (NULL == ps_info) + { + NSFW_LOGERR ("ps_info nul!"); + return FALSE; + } + + if (NSFW_PROC_APP != ps_info->proc_type) + { + return FALSE; + } + + if (NSFW_PS_EXITING != ps_info->state) + { + return FALSE; + } + + ps_info->resend_timer_ptr = NULL; + (void) mem_ps_exiting (ps_info, NULL); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_ps_exiting +* Description : send exiting message when ps_info exiting +* Input : void *pps_info +* void* argv +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_ps_exiting (void *pps_info, void *argv) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("ps_info nul!"); + return FALSE; + } + + if (TRUE == NSFW_SRV_STATE_SUSPEND) + { + NSFW_LOGERR ("main suspend]ps_info=%d,pid=%u", pps_info, + ((nsfw_ps_info *) pps_info)->host_pid); + return FALSE; + } + + nsfw_mgr_msg *msg = + nsfw_mgr_msg_alloc (MGR_MSG_APP_EXIT_REQ, NSFW_PROC_MAIN); + if (NULL == msg) + { + NSFW_LOGERR ("ps_exit alloc msg failed]ps_info=%p,pid=%u", pps_info, + ((nsfw_ps_info *) pps_info)->host_pid); + return FALSE; + } + + nsfw_ps_info_msg *ps_msg = GET_USER_MSG (nsfw_ps_info_msg, msg); + ps_msg->host_pid = ((nsfw_ps_info *) pps_info)->host_pid; + + (void) nsfw_mgr_send_msg (msg); + NSFW_LOGINF ("ps_exiting send msg]ps_info=%p,pid=%u", pps_info, + ps_msg->host_pid); + nsfw_mgr_msg_free (msg); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_alloc_ps_info +* Description : alloc ps_info +* Input : u32 pid +* u8 proc_type +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_alloc_ps_info (u32 pid, u8 proc_type) +{ + nsfw_ps_info *pps_info = NULL; + pps_info = nsfw_ps_info_get (pid); + if (NULL != pps_info) + { + return TRUE; + } + + pps_info = nsfw_ps_info_alloc (pid, proc_type); + if (NULL == pps_info) + { + NSFW_LOGERR ("alloc ps_info falied!]pid=%u,proc_type=%u", pid, + proc_type); + return FALSE; + } + + NSFW_LOGINF ("alloc new ps_info]pps_info=%p,pid=%u", pps_info, pid); + return TRUE; +} + +/*mem alloc by msg begin*/ +void * +mem_item_zone_create (void *mem_info) +{ + return (void *) nsfw_mem_zone_create ((nsfw_mem_zone *) mem_info); +} + +void * +mem_item_mbfmp_create (void *mem_info) +{ + return (void *) nsfw_mem_mbfmp_create ((nsfw_mem_mbfpool *) mem_info); +} + +void * +mem_item_sp_create (void *mem_info) +{ + return (void *) nsfw_mem_sp_create ((nsfw_mem_sppool *) mem_info); +} + +void * +mem_item_ring_create (void *mem_info) +{ + return (void *) nsfw_mem_ring_create ((nsfw_mem_mring *) mem_info); +} + +nsfw_ps_mem_item_cfg g_ps_mem_map[] = { + { + NSFW_RESERV_REQ_MSG, + sizeof (nsfw_shmem_reserv_req), + NSFW_MEM_MZONE, + mem_item_zone_create, + mem_item_get_callargv} + , + + { + NSFW_MBUF_REQ_MSG, + sizeof (nsfw_shmem_mbuf_req), + NSFW_MEM_MBUF, + mem_item_mbfmp_create, + mem_item_get_callargv} + , + { + NSFW_SPPOOL_REQ_MSG, + sizeof (nsfw_shmem_sppool_req), + NSFW_MEM_SPOOL, + mem_item_sp_create, + mem_item_get_callargv} + , + { + NSFW_RING_REQ_MSG, + sizeof (nsfw_shmem_ring_req), + NSFW_MEM_RING, + mem_item_ring_create, + mem_item_get_callargv} + , + { + NSFW_RELEASE_REQ_MSG, + sizeof (nsfw_shmem_free_req), + 0xFFFF, + mem_item_free, + mem_item_get_callargv, + } + , + { + NSFW_MEM_LOOKUP_REQ_MSG, + sizeof (nsfw_shmem_lookup_req), + 0xFFFF, + mem_item_lookup, + mem_item_get_callargv, + } +}; + +/***************************************************************************** +* Prototype : mem_item_get_cfg_from_msg +* Description : get memory config +* Input : u16 msg_type +* Output : None +* Return Value : nsfw_ps_mem_item_cfg * +* Calls : +* Called By : +*****************************************************************************/ +nsfw_ps_mem_item_cfg * +mem_item_get_cfg_from_msg (u16 msg_type) +{ + int idx; + int map_count = sizeof (g_ps_mem_map) / sizeof (nsfw_ps_mem_item_cfg); + for (idx = 0; idx < map_count; idx++) + { + if (g_ps_mem_map[idx].usmsg_type == msg_type) + { + return &g_ps_mem_map[idx]; + } + } + + return NULL; +} + +/***************************************************************************** +* Prototype : mem_item_get_callargv +* Description : change the message value to structur value +* Input : u16 msg_type +* char* msg_body +* char *memstr_buf +* i32 buf_len +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_item_get_callargv (u16 msg_type, char *msg_body, char *memstr_buf, + i32 buf_len) +{ + switch (msg_type) + { + case NSFW_RESERV_REQ_MSG: + MEM_GET_CALLARGV (lenth, lenth, nsfw_mem_zone, nsfw_shmem_reserv_req, + memstr_buf, msg_body); + MEM_GET_CALLARGV (isocket_id, isocket_id, nsfw_mem_zone, + nsfw_shmem_reserv_req, memstr_buf, msg_body); + break; + case NSFW_MBUF_REQ_MSG: + MEM_GET_CALLARGV (usnum, usnum, nsfw_mem_mbfpool, nsfw_shmem_mbuf_req, + memstr_buf, msg_body); + MEM_GET_CALLARGV (uscash_size, uscash_size, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (uspriv_size, uspriv_size, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (usdata_room, usdata_room, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (enmptype, enmptype, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (isocket_id, isocket_id, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + break; + case NSFW_SPPOOL_REQ_MSG: + MEM_GET_CALLARGV (usnum, usnum, nsfw_mem_sppool, + nsfw_shmem_sppool_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (useltsize, useltsize, nsfw_mem_sppool, + nsfw_shmem_sppool_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (enmptype, enmptype, nsfw_mem_sppool, + nsfw_shmem_sppool_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (isocket_id, isocket_id, nsfw_mem_sppool, + nsfw_shmem_sppool_req, memstr_buf, msg_body); + break; + case NSFW_RING_REQ_MSG: + MEM_GET_CALLARGV (usnum, usnum, nsfw_mem_mring, nsfw_shmem_ring_req, + memstr_buf, msg_body); + MEM_GET_CALLARGV (enmptype, enmptype, nsfw_mem_mring, + nsfw_shmem_ring_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (isocket_id, isocket_id, nsfw_mem_mring, + nsfw_shmem_ring_req, memstr_buf, msg_body); + break; + case NSFW_RELEASE_REQ_MSG: + MEM_GET_CALLARGV (ustype, ustype, nsfw_mem_type_info, + nsfw_shmem_free_req, memstr_buf, msg_body); + break; + case NSFW_MEM_LOOKUP_REQ_MSG: + MEM_GET_CALLARGV (ustype, ustype, nsfw_mem_type_info, + nsfw_shmem_lookup_req, memstr_buf, msg_body); + break; + default: + NSFW_LOGERR ("error msg]type=%u", msg_type); + return FALSE; + } + if (EOK != + STRCPY_S (((nsfw_mem_zone *) memstr_buf)->stname.aname, + NSFW_MEM_NAME_LENTH, + ((nsfw_shmem_reserv_req *) msg_body)->aname)) + { + NSFW_LOGERR ("STRCPY_S failed]msg_type=%u", msg_type); + return FALSE; + } + + ((nsfw_mem_zone *) memstr_buf)->stname.entype = NSFW_SHMEM; + + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_item_free +* Description : free memory item +* Input : void *pdata +* Output : None +* Return Value : void* +* Calls : +* Called By : +*****************************************************************************/ +void * +mem_item_free (void *pdata) +{ + nsfw_mem_type_info *mem_free = (nsfw_mem_type_info *) pdata; + i32 ret; + NSFW_LOGINF ("free mem]type=%u,name=%s", mem_free->ustype, + mem_free->stname.aname); + switch (mem_free->ustype) + { + case NSFW_MEM_MZONE: + ret = nsfw_mem_zone_release (&mem_free->stname); + break; + case NSFW_MEM_MBUF: + ret = nsfw_mem_mbfmp_release (&mem_free->stname); + break; + case NSFW_MEM_SPOOL: + ret = nsfw_mem_sp_release (&mem_free->stname); + break; + case NSFW_MEM_RING: + ret = nsfw_mem_ring_release (&mem_free->stname); + break; + default: + NSFW_LOGERR ("free mem err type]type=%u", mem_free->ustype); + return NULL; + } + + if (NSFW_MEM_OK != ret) + { + NSFW_LOGERR ("mem free failed!]ret=%d", ret); + return NULL; + } + + return pdata; +} + +/***************************************************************************** +* Prototype : mem_item_lookup +* Description : lookup memory item +* Input : void *pdata +* Output : None +* Return Value : void* +* Calls : +* Called By : +*****************************************************************************/ +void * +mem_item_lookup (void *pdata) +{ + nsfw_mem_type_info *mem_lookup = (nsfw_mem_type_info *) pdata; + void *ret; + NSFW_LOGDBG ("lookup mem]type=%u,name=%s", mem_lookup->ustype, + mem_lookup->stname.aname); + switch (mem_lookup->ustype) + { + case NSFW_MEM_MZONE: + ret = nsfw_mem_zone_lookup (&mem_lookup->stname); + break; + case NSFW_MEM_MBUF: + ret = nsfw_mem_mbfmp_lookup (&mem_lookup->stname); + break; + case NSFW_MEM_SPOOL: + ret = nsfw_mem_sp_lookup (&mem_lookup->stname); + break; + case NSFW_MEM_RING: + ret = nsfw_mem_ring_lookup (&mem_lookup->stname); + break; + default: + NSFW_LOGERR ("lookup mem err type]type=%d", mem_lookup->ustype); + return NULL; + } + + if (NULL == ret) + { + NSFW_LOGERR ("mem lookup failed!]ret=%p,name=%s", ret, + mem_lookup->stname.aname); + return NULL; + } + + return ret; +} + +/***************************************************************************** +* Prototype : mem_item_proc_by_msg +* Description : call memory item process function +* Input : void *pdata +* nsfw_ps_mem_item_cfg* item_cfg +* Output : None +* Return Value : void* +* Calls : +* Called By : +*****************************************************************************/ +void * +mem_item_proc_by_msg (void *pdata, nsfw_ps_mem_item_cfg * item_cfg) +{ + char argv_buf[NSFW_MEM_CALL_ARG_BUF] = { 0 }; + + if ((NULL == item_cfg->change_fun) || (NULL == item_cfg->create_fun)) + { + NSFW_LOGERR ("item error]change_fun=%p,create_fun=%p", + item_cfg->change_fun, item_cfg->create_fun); + return NULL; + } + + if (FALSE == + item_cfg->change_fun (item_cfg->usmsg_type, pdata, argv_buf, + NSFW_MEM_CALL_ARG_BUF)) + { + NSFW_LOGERR ("call change_fun failed!]type=%u", item_cfg->usmsg_type); + return NULL; + } + + void *pdataret = NULL; + pdataret = (item_cfg->create_fun) ((void *) argv_buf); + return pdataret; +} + +/***************************************************************************** +* Prototype : mem_init_rsp_msg +* Description : init the rsp message +* Input : nsfw_shmem_msg_head* msg +* nsfw_shmem_msg_head *rsp +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +u8 +mem_init_rsp_msg (nsfw_shmem_msg_head * msg, nsfw_shmem_msg_head * rsp) +{ + nsfw_ps_mem_item_cfg *item_cfg = + mem_item_get_cfg_from_msg (msg->usmsg_type); + if (NULL == item_cfg) + { + NSFW_LOGERR ("get item cfg failed!]msg_type=%u", msg->usmsg_type); + return FALSE; + } + + int idx; + int mem_count = msg->uslenth / item_cfg->item_size; + + rsp->usmsg_type = msg->usmsg_type + 1; + rsp->uslenth = mem_count * sizeof (nsfw_shmem_ack); + nsfw_shmem_ack *pack = (nsfw_shmem_ack *) & (rsp->aidata[0]); + char *pdata = NULL; + for (idx = 0; idx < mem_count; idx++) + { + pdata = (char *) msg->aidata + idx * item_cfg->item_size; + pack->pbase_addr = NULL; + pack->usseq = ((nsfw_shmem_reserv_req *) pdata)->usseq; + pack->cstate = NSFW_MEM_ALLOC_FAIL; + pack++; + } + + NSFW_LOGDBG ("init all rsp ack]mem_count=%d,msg_type=%u", mem_count, + msg->usmsg_type); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_rel_mem_by_msg +* Description : release memory by message +* Input : nsfw_shmem_msg_head* req_msg +* nsfw_shmem_msg_head *rsp +* u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_rel_mem_by_msg (nsfw_shmem_msg_head * req_msg, + nsfw_shmem_msg_head * rsp, u32 pid) +{ + u32 i; + nsfw_ps_mem_item_cfg *item_cfg = + mem_item_get_cfg_from_msg (req_msg->usmsg_type); + if (NULL == item_cfg) + { + NSFW_LOGERR ("get item cfg failed!]msg_type=%u", req_msg->usmsg_type); + return FALSE; + } + + unsigned int mem_count = req_msg->uslenth / item_cfg->item_size; + char *pdata = NULL; + nsfw_shmem_ack *pack = (nsfw_shmem_ack *) & (rsp->aidata[0]); + for (i = 0; i < mem_count; i++) + { + pdata = (char *) req_msg->aidata + i * item_cfg->item_size; + if (NULL != mem_item_proc_by_msg ((void *) pdata, item_cfg)) + { + pack->cstate = NSFW_MEM_ALLOC_SUCC; + pack->pbase_addr = NULL; + } + pack++; + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_lookup_mem_by_msg +* Description : lookup memory by message +* Input : nsfw_shmem_msg_head* mgr_msg +* nsfw_shmem_msg_head *rsp +* u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_lookup_mem_by_msg (nsfw_shmem_msg_head * mgr_msg, + nsfw_shmem_msg_head * rsp, u32 pid) +{ + i32 idx; + nsfw_ps_mem_item_cfg *item_cfg = + mem_item_get_cfg_from_msg (mgr_msg->usmsg_type); + if (NULL == item_cfg) + { + NSFW_LOGERR ("get item cfg failed!]msg_type=%u", mgr_msg->usmsg_type); + return FALSE; + } + + int mem_count = mgr_msg->uslenth / item_cfg->item_size; + char *pdata = NULL; + void *paddr = NULL; + nsfw_shmem_ack *pack = (nsfw_shmem_ack *) & (rsp->aidata[0]); + + for (idx = 0; idx < mem_count; idx++) + { + pdata = (char *) mgr_msg->aidata + idx * item_cfg->item_size; + paddr = mem_item_proc_by_msg ((void *) pdata, item_cfg); + if (NULL != paddr) + { + pack->cstate = NSFW_MEM_ALLOC_SUCC; + pack->pbase_addr = paddr; + } + pack++; + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_alloc_mem_by_msg +* Description : alloc memory by message +* Input : nsfw_shmem_msg_head* mem_msg +* nsfw_shmem_msg_head *rsp +* Output : None +* Return Value : ns_mem_info* +* Calls : +* Called By : +*****************************************************************************/ +void * +mem_alloc_mem_by_msg (nsfw_shmem_msg_head * mem_msg, + nsfw_shmem_msg_head * rsp) +{ + nsfw_ps_mem_item_cfg *item_cfg = + mem_item_get_cfg_from_msg (mem_msg->usmsg_type); + if (NULL == item_cfg) + { + NSFW_LOGERR ("get item cfg failed!]msg_type=%u", mem_msg->usmsg_type); + return NULL; + } + + int i; + int j; + nsfw_mem_type_info mem_free; + char *pdata = NULL; + void *p_addr = NULL; + + int mem_count = mem_msg->uslenth / item_cfg->item_size; + nsfw_shmem_ack *pack = (nsfw_shmem_ack *) & (rsp->aidata[0]); + for (i = 0; i < mem_count; i++) + { + pdata = (char *) mem_msg->aidata + i * item_cfg->item_size; + p_addr = mem_item_proc_by_msg ((void *) pdata, item_cfg); + if (NULL == p_addr) + { + NSFW_LOGERR + ("alloc mem failed!]type=%u,mem_count=%d,item=%d,name=%s", + mem_msg->usmsg_type, mem_count, i, + ((nsfw_shmem_reserv_req *) pdata)->aname); + goto fail_free_mem; + } + + pack->cstate = NSFW_MEM_ALLOC_SUCC; + pack->pbase_addr = p_addr; + NSFW_LOGINF + ("alloc mem suc!]addr=%p,type=%u,mem_count=%d,item=%d,name=%s", + p_addr, mem_msg->usmsg_type, mem_count, i, + ((nsfw_shmem_reserv_req *) pdata)->aname); + pack++; + } + return p_addr; + +fail_free_mem: + for (j = 0; j < i; j++) + { + pdata = (char *) mem_msg->aidata + j * item_cfg->item_size; + if (EOK != + STRCPY_S (mem_free.stname.aname, NSFW_MEM_NAME_LENTH, + ((nsfw_shmem_reserv_req *) pdata)->aname)) + { + NSFW_LOGERR ("STRCPY_S failed]j=%d", j); + continue; + } + + mem_free.ustype = item_cfg->mem_type; + mem_free.stname.entype = NSFW_SHMEM; + (void) mem_item_free (&mem_free); + NSFW_LOGINF ("free mem]addr=%p,type=%u,mem_count=%d,item=%d,name=%s", + p_addr, mem_msg->usmsg_type, mem_count, j, + ((nsfw_shmem_reserv_req *) pdata)->aname); + pack++; + } + + return NULL; + +} + +/***************************************************************************** +* Prototype : mem_alloc_req_proc +* Description : memory message +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_alloc_req_proc (nsfw_mgr_msg * msg) +{ + void *mem_addr = NULL; + + if (NULL == msg) + { + NSFW_LOGERR ("msg nul"); + return FALSE; + } + + nsfw_shmem_msg_head *mem_msg = GET_USER_MSG (nsfw_shmem_msg_head, msg); + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp msg failed]msg_type=%u", mem_msg->usmsg_type); + return FALSE; + } + + nsfw_shmem_msg_head *mem_rsp_msg = + GET_USER_MSG (nsfw_shmem_msg_head, rsp_msg); + + if (!mem_init_rsp_msg (mem_msg, mem_rsp_msg)) + { + NSFW_LOGERR ("init rsp msg failed]msg_type=%u", mem_msg->usmsg_type); + nsfw_mgr_msg_free (rsp_msg); + return FALSE; + } + + switch (mem_msg->usmsg_type) + { + case NSFW_MEM_LOOKUP_REQ_MSG: + if (!mem_lookup_mem_by_msg (mem_msg, mem_rsp_msg, msg->src_pid)) + { + NSFW_LOGERR ("lookup mem msg failed]msg_type=%u", + mem_msg->usmsg_type); + goto sendrspmsg; + } + (void) mem_alloc_ps_info (msg->src_pid, msg->src_proc_type); + break; + case NSFW_RESERV_REQ_MSG: + case NSFW_MBUF_REQ_MSG: + case NSFW_SPPOOL_REQ_MSG: + case NSFW_RING_REQ_MSG: + mem_addr = mem_alloc_mem_by_msg (mem_msg, mem_rsp_msg); + if (NULL == mem_addr) + { + NSFW_LOGERR ("alloc mem msg failed]msg_type=%u", + mem_msg->usmsg_type); + (void) mem_init_rsp_msg (mem_msg, mem_rsp_msg); + goto sendrspmsg; + } + (void) mem_alloc_ps_info (msg->src_pid, msg->src_proc_type); + break; + case NSFW_RELEASE_REQ_MSG: + if (!mem_rel_mem_by_msg (mem_msg, mem_rsp_msg, msg->src_pid)) + { + NSFW_LOGERR ("rel mem msg failed]msg_type=%u", mem_msg->usmsg_type); + goto sendrspmsg; + } + break; + default: + break; + } + +sendrspmsg: + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_ps_exiting_resend +* Description : send the exiting message again +* Input : void *pps_info +* void* argv +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_ps_exiting_resend (void *pps_info, void *argv) +{ + u32 *count = argv; + nsfw_ps_info *ps_info = pps_info; + if (NULL == ps_info) + { + NSFW_LOGERR ("ps_info nul!"); + return FALSE; + } + + if (NSFW_PROC_APP != ps_info->proc_type) + { + return FALSE; + } + + if (NSFW_PS_EXITING != ps_info->state) + { + return FALSE; + } + + if (NULL != count) + { + NSFW_LOGINF ("send count]count=%u,pid=%u", *count, ps_info->host_pid); + if (NSFW_PS_SEND_PER_TIME < (*count)++) + { + struct timespec time_left = + { NSFW_PS_MEM_RESEND_TVLAUE + +((*count) / NSFW_PS_SEND_PER_TIME), 0 + }; + ps_info->resend_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_PS_MEM_RESEND_TIMER, + pps_info, + nsfw_mem_ps_exit_resend_timeout, + time_left); + return TRUE; + } + } + + (void) mem_ps_exiting (ps_info, NULL); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mem_srv_restore_timeout +* Description : service waiting resume timeout +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mem_srv_restore_timeout (u32 timer_type, void *data) +{ + u32 max_count = 0; + + g_mem_cfg.p_restore_timer = NULL; + if (TRUE == NSFW_SRV_STATE_SUSPEND) + { + NSFW_SRV_STATE_SUSPEND = FALSE; + (void) nsfw_ps_iterator (mem_ps_exiting_resend, &max_count); + } + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_srv_ctrl_proc +* Description : service control message process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_srv_ctrl_proc (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("msg nul"); + return FALSE; + } + + nsfw_srv_ctrl_msg *ctrl_msg = GET_USER_MSG (nsfw_srv_ctrl_msg, msg); + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp msg failed]msg=%p", msg); + return FALSE; + } + nsfw_srv_ctrl_msg *ctrl_rsp_msg = GET_USER_MSG (nsfw_srv_ctrl_msg, rsp_msg); + NSFW_LOGINF ("get srv ctrl state] state=%d", ctrl_msg->srv_state); + + ctrl_rsp_msg->rsp_code = NSFW_MGR_SUCESS; + + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + + if (NSFW_SRV_CTRL_RESUME == ctrl_msg->srv_state) + { + if (TRUE == NSFW_SRV_STATE_SUSPEND) + { + NSFW_SRV_STATE_SUSPEND = FALSE; + } + u32 max_count = 0; + (void) nsfw_ps_iterator (mem_ps_exiting_resend, &max_count); + if (NULL != g_mem_cfg.p_restore_timer) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) + g_mem_cfg.p_restore_timer); + g_mem_cfg.p_restore_timer = NULL; + } + } + else + { + NSFW_SRV_STATE_SUSPEND = TRUE; + struct timespec time_left = { NSFW_SRV_RESTORE_TVALUE, 0 }; + g_mem_cfg.p_restore_timer = + (void *) nsfw_timer_reg_timer (0, NULL, + nsfw_mem_srv_restore_timeout, + time_left); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_mem_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_mem_module_init (void *param) +{ + u32 proc_type = (u32) ((long long) param); + NSFW_LOGINF ("ps_mem module init]type=%u", proc_type); + switch (proc_type) + { + case NSFW_PROC_MAIN: + (void) nsfw_ps_reg_global_fun (NSFW_PROC_APP, NSFW_PS_EXITING, + mem_ps_exiting, NULL); + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_MEM_ALLOC_REQ, mem_alloc_req_proc); + (void) NSFW_REG_SOFT_INT (NSFW_SRV_RESTORE_TIMER, + NSFW_SRV_RESTORE_TVALUE, 1, 0xFFFF); + (void) NSFW_REG_SOFT_INT (NSFW_APP_RESEND_TIMER, + NSFW_PS_MEM_RESEND_TVLAUE, 1, 0xFFFF); + (void) NSFW_REG_SOFT_INT (NSFW_APP_SEND_PER_TIME, + NSFW_PS_SEND_PER_TIME, 1, 0xFFFF); + break; + default: + if (proc_type < NSFW_PROC_MAX) + { + return 0; + } + return -1; + } + + g_mem_cfg.srv_restore_tvalue = NSFW_SRV_RESTORE_TVALUE_DEF; + g_mem_cfg.ps_exit_resend_tvalue = NSFW_PS_MEM_RESEND_TVLAUE_DEF; + g_mem_cfg.ps_send_per_time = NSFW_PS_SEND_PER_TIME_DEF; + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_PS_MEM_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_PS_MODULE) +NSFW_MODULE_INIT (nsfw_ps_mem_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/ps/nsfw_ps_mem_module.h b/src/framework/ipc/ps/nsfw_ps_mem_module.h new file mode 100644 index 0000000..6b2b3c9 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_ps_mem_module.h @@ -0,0 +1,87 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_PS_MEM_MODULE_H +#define _NSFW_PS_MEM_MODULE_H + +#include "list.h" +#include "pidinfo.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define MEMZONE_MAX_NAME 32 +#define NS_MAX_FORK_NUM 32 +#define NSFW_PS_MEM_MAX_FILTER 4 + +#define NSFW_SRV_RESTORE_TVALUE_DEF 120 +#define NSFW_SRV_RESTORE_TVALUE g_mem_cfg.srv_restore_tvalue +#define NSFW_SRV_STATE_SUSPEND g_mem_cfg.srv_suspend + +#define NSFW_PS_MEM_RESEND_TIMER 1 +#define NSFW_PS_MEM_RESEND_TVLAUE_DEF 2 +#define NSFW_PS_SEND_PER_TIME_DEF 150 +#define NSFW_PS_SEND_PER_TIME (g_mem_cfg.ps_send_per_time) +#define NSFW_PS_MEM_RESEND_TVLAUE (g_mem_cfg.ps_exit_resend_tvalue) + +typedef struct _ns_mem_mng_init_cfg +{ + u16 srv_restore_tvalue; + u16 ps_exit_resend_tvalue; + u16 ps_send_per_time; + u16 srv_suspend; + void *p_restore_timer; +} ns_mem_mng_init_cfg; + +/*mem alloc by msg begin*/ +typedef struct +{ + nsfw_mem_name stname; + u16 ustype; +} nsfw_mem_type_info; + +#define NSFW_MEM_CALL_ARG_BUF 256 +#define MEM_GET_CALLARGV(_dst_member,_src_member, _dst_type,_srctype,_dst_buf, _src_buf) \ + ((_dst_type*)(void*)_dst_buf)->_dst_member = ((_srctype*)(void*)_src_buf)->_src_member + +typedef void *(*nsfw_ps_mem_create_fun) (void *memstr); +typedef u8 (*nsfw_ps_mem_msg_to_memstr) (u16 msg_type, char *msg_body, + char *memstr_buf, i32 buf_len); + +typedef struct __nsfw_ps_mem_item_cfg +{ + u16 usmsg_type; + u16 item_size; + u16 mem_type; + nsfw_ps_mem_create_fun create_fun; + nsfw_ps_mem_msg_to_memstr change_fun; +} nsfw_ps_mem_item_cfg; + +void *mem_item_free (void *pdata); +void *mem_item_lookup (void *pdata); +u8 mem_item_get_callargv (u16 msg_type, char *msg_body, char *memstr_buf, + i32 buf_len); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_PS_MEM_MODULE_H */ diff --git a/src/framework/ipc/ps/nsfw_ps_module.c b/src/framework/ipc/ps/nsfw_ps_module.c new file mode 100644 index 0000000..e532c31 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_ps_module.c @@ -0,0 +1,1725 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nsfw_mgr_com_api.h" +#include "nsfw_ps_api.h" +#include "nsfw_ps_module.h" +#include "nsfw_mem_api.h" +#include "nstack_log.h" +#include "nsfw_base_linux_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_maintain_api.h" + +#include <errno.h> +#include <sys/un.h> +#include <stddef.h> +#include <sys/epoll.h> +#include <fcntl.h> + +#include <linux/cn_proc.h> +#include <linux/connector.h> +#include <linux/netlink.h> +#include <dirent.h> +#include <fnmatch.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +nsfw_ps_init_cfg g_ps_cfg; + +nsfw_pid_item *g_ps_info = NULL; + +nsfw_pid_item *g_master_ps_info = NULL; + +struct list_head g_ps_runing_list; +nsfw_ps_callback g_ps_init_callback[NSFW_PROC_MAX][NSFW_PS_MAX_CALLBACK]; +nsfw_ps_info g_main_ps_info; + +void *g_ps_chk_timer = NULL; + +/***************************************************************************** +* Prototype : nsfw_ps_reg_fun +* Description : reg the callback fun when process state change +* Input : nsfw_ps_info *pps_info +* u8 ps_state +* nsfw_ps_proc_fun fun +* void* argv +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_reg_fun (nsfw_ps_info * pps_info, u8 ps_state, + nsfw_ps_proc_fun fun, void *argv) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("reg pps_info nul]state=%d,fun=%p", ps_state, fun); + return FALSE; + } + + u32 i; + for (i = 0; i < NSFW_PS_MAX_CALLBACK; i++) + { + if (NULL == pps_info->callback[i].fun) + { + pps_info->callback[i].fun = fun; + pps_info->callback[i].argv = argv; + pps_info->callback[i].state = ps_state; + NSFW_LOGDBG + ("reg fun suc]ps_info=%p,state=%d,fun=%p,argv=%p,i=%d", + pps_info, ps_state, fun, argv, i); + return TRUE; + } + } + + NSFW_LOGERR ("reg fun failed]ps_info=%p,state=%d,fun=%p,argv=%p,i=%d", + pps_info, ps_state, fun, argv, i); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_reg_global_fun +* Description : reg the callback function of the specify proc_type state + change +* Input : u8 proc_type +* u8 ps_state +* nsfw_ps_proc_fun fun +* void* argv +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_reg_global_fun (u8 proc_type, u8 ps_state, nsfw_ps_proc_fun fun, + void *argv) +{ + if (NSFW_PROC_MAX <= proc_type) + { + NSFW_LOGERR ("proc_type err]state=%u,fun=%p,type=%u", ps_state, fun, + proc_type); + return FALSE; + } + + nsfw_ps_callback *cb_fun = g_ps_init_callback[proc_type]; + u32 i; + for (i = 0; i < NSFW_PS_MAX_CALLBACK; i++) + { + if (NULL == cb_fun[i].fun) + { + cb_fun[i].fun = fun; + cb_fun[i].argv = argv; + cb_fun[i].state = ps_state; + NSFW_LOGINF ("reg fun suc]type=%u,state=%u,fun=%p,argv=%p,i=%u", + proc_type, ps_state, fun, argv, i); + return TRUE; + } + } + + NSFW_LOGERR ("reg fun ful failed]type=%u,state=%u,fun=%p,argv=%p,i=%u", + proc_type, ps_state, fun, argv, i); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_exit +* Description : when recvive the process exit finish message ,change + to exit state +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_exit (nsfw_mgr_msg * msg) +{ + nsfw_ps_info *pps_info; + if (NULL == msg) + { + NSFW_LOGERR ("msg nul!"); + return FALSE; + } + + nsfw_ps_info_msg *ps_msg = GET_USER_MSG (nsfw_ps_info_msg, msg); + pps_info = nsfw_ps_info_get (ps_msg->host_pid); + NSFW_LOGINF ("recv ps exit]host_pid=%d,ps_info=%p", ps_msg->host_pid, + pps_info); + + if (NULL == pps_info) + { + NSFW_LOGERR ("error msg pps_info nul]host_pid=%d", ps_msg->host_pid); + return true; + } + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXIT); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_info_fork_alloc +* Description : alloc fork ps_info +* Input : u32 parent_pid +* u32 child_pid +* Output : None +* Return Value : nsfw_ps_info* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_ps_info * +nsfw_ps_info_fork_alloc (u32 parent_pid, u32 child_pid) +{ + nsfw_ps_info *pps_info = NULL; + nsfw_ps_info *pps_info_parent = NULL; + pps_info_parent = nsfw_ps_info_get (parent_pid); + if (NULL == pps_info_parent) + { + NSFW_LOGERR ("pps_info_parent nul"); + return NULL; + } + + pps_info = nsfw_ps_info_get (child_pid); + if (NULL == pps_info) + { + pps_info = nsfw_ps_info_alloc (child_pid, pps_info_parent->proc_type); + if (NULL == pps_info) + { + NSFW_LOGERR + ("alloc ps_info failed!]ps_info=%p,host_pid=%u,child_pid=%u", + pps_info_parent, pps_info_parent->host_pid, child_pid); + return NULL; + } + } + else + { + NSFW_LOGWAR + ("fork alloc mem before!]ps_info=%p,host_pid=%u,child_pid=%u", + pps_info_parent, pps_info_parent->host_pid, child_pid); + } + + NSFW_LOGWAR ("ps_info fork]ps_info=%p,host_pid=%u,child_pid=%u", + pps_info_parent, pps_info_parent->host_pid, child_pid); + pps_info->parent_pid = parent_pid; + if (EOK != + MEMCPY_S (pps_info->callback, sizeof (pps_info->callback), + pps_info_parent->callback, + sizeof (pps_info_parent->callback))) + { + nsfw_ps_info_free (pps_info); + NSFW_LOGERR ("ps_info set_failed"); + return NULL; + } + + if (EOK != + MEMCPY_S (pps_info->value, sizeof (pps_info->value), + pps_info_parent->value, sizeof (pps_info_parent->value))) + { + nsfw_ps_info_free (pps_info); + NSFW_LOGERR ("ps_info cpy_failed"); + return NULL; + } + + return pps_info; +} + +/***************************************************************************** +* Prototype : nsfw_ps_info_alloc +* Description : alloc ps_info +* Input : u32 pid +* u8 proc_type +* Output : None +* Return Value : nsfw_ps_info* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_ps_info * +nsfw_ps_info_alloc (u32 pid, u8 proc_type) +{ + nsfw_ps_info *pps_info = NULL; + if (0 == nsfw_mem_ring_dequeue (g_ps_cfg.ps_info_pool, (void *) &pps_info)) + { + NSFW_LOGERR ("alloc ps_info falied]pid=%u,type=%u", pid, proc_type); + return NULL; + } + + if (NULL == pps_info) + { + if (NSFW_PROC_MAIN != proc_type || TRUE == g_main_ps_info.alloc_flag) + { + NSFW_LOGERR ("alloc ps_info nul]pid=%u,type=%u", pid, proc_type); + return NULL; + } + pps_info = &g_main_ps_info; + } + + if (EOK != + MEMSET_S (pps_info, sizeof (nsfw_ps_info), 0, sizeof (nsfw_ps_info))) + { + nsfw_ps_info_free (pps_info); + NSFW_LOGERR ("set failed"); + return NULL; + } + + pps_info->proc_type = proc_type; + pps_info->host_pid = pid; + + if (proc_type < NSFW_PROC_MAX) + { + int retval; + retval = + MEMCPY_S (pps_info->callback, sizeof (pps_info->callback), + g_ps_init_callback[proc_type], sizeof (pps_info->callback)); + if (EOK != retval) + { + NSFW_LOGERR ("Failed to MEMCPY_S]retval=%d", retval); + nsfw_ps_info_free (pps_info); + return NULL; + } + } + list_add_tail (&pps_info->node, &g_ps_runing_list); + pps_info->alloc_flag = TRUE; + + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_RUNNING); + if (pid < NSFW_MAX_PID) + { + g_ps_info[pid].ps_info = pps_info; + g_ps_info[pid].proc_type = proc_type; + } + + NSFW_LOGINF ("ps_info alloc]ps_info=%p,pid=%u,type=%u", pps_info, pid, + proc_type); + return pps_info; + +} + +/***************************************************************************** +* Prototype : nsfw_ps_info_get +* Description : get ps_info by pid +* Input : u32 pid +* Output : None +* Return Value : inline nsfw_ps_info* +* Calls : +* Called By : +*****************************************************************************/ +inline nsfw_ps_info * +nsfw_ps_info_get (u32 pid) +{ + if (pid < NSFW_MAX_PID) + { + return g_ps_info[pid].ps_info; + } + + return NULL; +} + +nsfw_ps_info * +nsfw_share_ps_info_get (u32 pid) +{ + if (pid < NSFW_MAX_PID) + { + return g_master_ps_info[pid].ps_info; + } + + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_ps_info_free +* Description : free ps_info +* Input : nsfw_ps_info *ps_info +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_ps_info_free (nsfw_ps_info * ps_info) +{ + if (NULL == ps_info) + { + NSFW_LOGERR ("ps_info nul"); + return; + } + + if (FALSE == ps_info->alloc_flag) + { + NSFW_LOGERR ("ps_info refree]ps_info=%p,pid=%u,state=%u", ps_info, + ps_info->host_pid, ps_info->state); + return; + } + + if (NULL != ps_info->exit_timer_ptr) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) ps_info->exit_timer_ptr); + ps_info->exit_timer_ptr = NULL; + } + + if (NULL != ps_info->resend_timer_ptr) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) ps_info->resend_timer_ptr); + ps_info->resend_timer_ptr = NULL; + } + + if (NULL != ps_info->hbt_timer_ptr) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) ps_info->hbt_timer_ptr); + ps_info->hbt_timer_ptr = NULL; + } + + list_del (&ps_info->node); + + ps_info->alloc_flag = FALSE; + + NSFW_LOGINF ("ps_info free]ps_info=%p,pid=%u,state=%u", ps_info, + ps_info->host_pid, ps_info->state); + if (ps_info != &g_main_ps_info) + { + if (0 == nsfw_mem_ring_enqueue (g_ps_cfg.ps_info_pool, ps_info)) + { + NSFW_LOGERR ("ps_info free failed]ps_info=%p,pid=%u,state=%u", + ps_info, ps_info->host_pid, ps_info->state); + return; + } + } + + if (ps_info->host_pid < NSFW_MAX_PID) + { + g_ps_info[ps_info->host_pid].proc_type = 0; + g_ps_info[ps_info->host_pid].ps_info = NULL; + } + + return; +} + +/***************************************************************************** +* Prototype : nsfw_ps_exiting_timeout +* Description : waiting for remove ps_info timeout +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_exiting_timeout (u32 timer_type, void *data) +{ + nsfw_ps_info *pps_info = (nsfw_ps_info *) data; + NSFW_LOGINF ("ps_info timerout]pps_info=%p,pid=%u", pps_info, + pps_info->host_pid); + if (NULL == pps_info) + { + return TRUE; + } + + pps_info->exit_timer_ptr = NULL; + + if (TRUE == g_hbt_switch) + { + NSFW_LOGINF ("hbt off"); + struct timespec time_left = { NSFW_PS_WEXIT_TVLAUE, 0 }; + pps_info->exit_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_PS_WEXIT_TIMER, pps_info, + nsfw_ps_exiting_timeout, time_left); + return TRUE; + } + + if (NSFW_PS_EXITING == pps_info->state) + { + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXIT); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_exit_end_notify +* Description : send exitting state process finished +* Input : u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_exit_end_notify (u32 pid) +{ + nsfw_mgr_msg *rsp_msg = + nsfw_mgr_msg_alloc (MGR_MSG_APP_EXIT_RSP, NSFW_PROC_MASTER); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp msg failed]pid=%u", pid); + return FALSE; + } + + nsfw_ps_info_msg *ps_msg = GET_USER_MSG (nsfw_ps_info_msg, rsp_msg); + ps_msg->host_pid = pid; + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + NSFW_LOGINF ("send exit rsp msg]pid=%u", pid); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_sw_ps_state +* Description : switch ps_info state +* Input : nsfw_ps_info* pps_info +* u8 new_state +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_sw_ps_state (nsfw_ps_info * pps_info, u8 new_state) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("pps_info nul!"); + return FALSE; + } + + NSFW_LOGINF ("sw]ps_info=%p,pid=%u,type=%u,old_state=%u,newstate=%u", + pps_info, pps_info->host_pid, pps_info->proc_type, + pps_info->state, new_state); + + i32 i, ret; + for (i = 0; i < NSFW_PS_MAX_CALLBACK; i++) + { + if (NULL == pps_info->callback[i].fun) + { + /* NULL should be the last fun */ + break; + } + + if (new_state == pps_info->callback[i].state) + { + ret = + pps_info->callback[i].fun (pps_info, pps_info->callback[i].argv); + NSFW_LOGINF ("callback fun]ps_info=%p,i=%d,fun=%p,argv=%p,ret=%d", + pps_info, i, pps_info->callback[i].fun, + pps_info->callback[i].argv, ret); + } + } + + if (NSFW_PS_HBT_FAILED != new_state) + { + pps_info->state = new_state; + } + + if (NSFW_PS_EXIT == new_state) + { + nsfw_ps_info_free (pps_info); + } + + if (NSFW_PS_EXITING == new_state) + { + struct timespec time_left = { NSFW_PS_WEXIT_TVLAUE, 0 }; + pps_info->exit_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_PS_WEXIT_TIMER, pps_info, + nsfw_ps_exiting_timeout, time_left); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_get_netlink_socket +* Description : get netlink socket to kernel +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_ps_get_netlink_socket () +{ + int rc; + int nl_sock; + int size, size_len; + struct sockaddr_nl sa_nl; + + nl_sock = nsfw_base_socket (PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); + if (nl_sock == -1) + { + NSFW_LOGERR ("get netlink socket err]errno=%d", errno); + return -1; + } + + rc = nsfw_set_close_on_exec (nl_sock); + if (rc == -1) + { + (void) nsfw_base_close (nl_sock); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", nl_sock, errno); + return -1; + } + + sa_nl.nl_family = AF_NETLINK; + sa_nl.nl_groups = CN_IDX_PROC; + sa_nl.nl_pid = getpid (); + + rc = nsfw_base_bind (nl_sock, (struct sockaddr *) &sa_nl, sizeof (sa_nl)); + if (rc == -1) + { + (void) nsfw_base_close (nl_sock); + NSFW_LOGERR ("netlink bind err]netlink_fd=%d, errno=%d", nl_sock, + errno); + return -1; + } + + struct __attribute__ ((aligned (NLMSG_ALIGNTO))) + { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) + { + struct cn_msg cn_msg; + enum proc_cn_mcast_op cn_mcast; + }; + } nlcn_msg; + if (EOK != MEMSET_S (&nlcn_msg, sizeof (nlcn_msg), 0, sizeof (nlcn_msg))) + { + (void) nsfw_base_close (nl_sock); + NSFW_LOGERR ("netlink set failed]netlink_fd=%d", nl_sock); + return -1; + } + nlcn_msg.nl_hdr.nlmsg_len = sizeof (nlcn_msg); + nlcn_msg.nl_hdr.nlmsg_pid = getpid (); + nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE; + + nlcn_msg.cn_msg.id.idx = CN_IDX_PROC; + nlcn_msg.cn_msg.id.val = CN_VAL_PROC; + nlcn_msg.cn_msg.len = sizeof (enum proc_cn_mcast_op); + + nlcn_msg.cn_mcast = PROC_CN_MCAST_LISTEN; + rc = nsfw_base_send (nl_sock, &nlcn_msg, sizeof (nlcn_msg), 0); + if (rc == -1) + { + (void) nsfw_base_close (nl_sock); + NSFW_LOGERR ("netlink send err]netlink_fd=%d, errno=%d", nl_sock, + errno); + return -1; + } + + NSFW_LOGINF ("netlink connect]netlink_fd=%d", nl_sock); + int val, len; + len = sizeof (val); + if (0 > + nsfw_base_getsockopt (nl_sock, SOL_SOCKET, SO_RCVBUF, &val, + (socklen_t *) & len)) + { + NSFW_LOGERR ("get socket opt err!]error=%d", errno); + } + else + { + NSFW_LOGINF ("] SO_RCVBUF=0x%x", val); + } + + size = MAX_NET_LINK_BUF; + size_len = sizeof (size); + if (0 > + nsfw_base_setsockopt (nl_sock, SOL_SOCKET, SO_RCVBUFFORCE, + (void *) &size, (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + size_len = sizeof (size); + if (0 > + nsfw_base_getsockopt (nl_sock, SOL_SOCKET, SO_RCVBUF, (void *) &size, + (socklen_t *) & size_len)) + { + NSFW_LOGERR ("get socket opt err!]error=%d", errno); + } + + NSFW_LOGINF ("] SO_RCVBUF=0x%x", size); + return nl_sock; +} + +/***************************************************************************** +* Prototype : nsfw_ps_change_fun +* Description : proc change when receive event from kernel +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_change_fun (i32 epfd, i32 fd, u32 events) +{ + i32 rc; + u32 host_pid; + nsfw_ps_info *pps_info = NULL; + + struct __attribute__ ((aligned (NLMSG_ALIGNTO))) + { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) + { + struct cn_msg cn_msg; + struct proc_event proc_ev; + }; + } nlcn_msg; + + if (!(events & EPOLLIN)) + { + return TRUE; + } + + while (1) + { + rc = nsfw_base_recv (fd, &nlcn_msg, sizeof (nlcn_msg), 0); + if (rc == 0) + { + NSFW_LOGWAR ("netlink recv 0]netlink_fd=%d,errno=%d", fd, errno); + break; + } + else if (rc == -1) + { + if (errno == EINTR || errno == EAGAIN) + { + break; + } + NSMON_LOGERR ("netlink recv]netlink_fd=%d,errno=%d", fd, errno); + if (errno == ENOBUFS) + { + struct timespec time_left = { NSFW_PS_FIRST_CHK_TVLAUE, 0 }; + g_ps_chk_timer = + (void *) nsfw_timer_reg_timer (NSFW_PS_CHK_TIMER, + (void *) FALSE, + nsfw_ps_chk_timeout, + time_left); + } + break; + } + + switch (nlcn_msg.proc_ev.what) + { + case PROC_EVENT_EXIT: + host_pid = nlcn_msg.proc_ev.event_data.exit.process_pid; + pps_info = nsfw_ps_info_get (host_pid); + if (NULL == pps_info) + { + NSFW_LOGDBG ("pps info is null]host pid=%d", host_pid); + break; + } + + if (NSFW_PS_EXITING == pps_info->state) + { + NSFW_LOGERR ("double pid info]ps_info=%p,pid=%d", pps_info, + host_pid); + break; + } + + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXITING); + break; + default: + break; + } + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_start_netlink +* Description : reg ps_module to epoll thread +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +u8 +nsfw_ps_start_netlink () +{ + i32 netlink_fd = nsfw_ps_get_netlink_socket (); + if (netlink_fd < 0) + { + NSFW_LOGERR ("get netlink failed!"); + return FALSE; + } + + NSFW_LOGINF ("start ps_info module!]netlink_fd=%d", netlink_fd); + (void) nsfw_mgr_reg_sock_fun (netlink_fd, nsfw_ps_change_fun); + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_APP_EXIT_RSP, nsfw_ps_exit); + return TRUE; +} + +/* for heartbeat check*/ + +NSTACK_STATIC __thread i32 t_val_idx = 0; +nsfw_thread_dogs g_thread_dogs[NSFW_MAX_THREAD_DOGS_COUNT]; +/***************************************************************************** +* Prototype : nsfw_all_thread_chk +* Description : get all thread check state +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_all_thread_chk () +{ + i32 count = -1; + u32 i; + for (i = 0; i < NSFW_MAX_THREAD_DOGS_COUNT; i++) + { + if (FALSE == g_thread_dogs[i].alloc_flag) + { + continue; + } + + if (count < g_thread_dogs[i].count) + { + count = g_thread_dogs[i].count; + } + + g_thread_dogs[i].count++; + } + return count; +} + +/***************************************************************************** +* Prototype : nsfw_thread_chk_unreg +* Description : cancel the thread check +* Input : None +* Output : None +* Return Value : inline u8 +* Calls : +* Called By : +*****************************************************************************/ +inline u8 +nsfw_thread_chk_unreg () +{ + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + g_thread_dogs[t_val_idx].alloc_flag = FALSE; + g_thread_dogs[t_val_idx].count = 0; + g_thread_dogs[t_val_idx].thread_id = 0; + t_val_idx = 0; + } + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_thread_chk +* Description : add the thread to check, and should be call in every + process cycle +* Input : None +* Output : None +* Return Value : inline u8 +* Calls : +* Called By : +*****************************************************************************/ +inline u8 +nsfw_thread_chk () +{ + u32 i; + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + g_thread_dogs[t_val_idx].count = 0; + return TRUE; + } + + for (i = 1; i < NSFW_MAX_THREAD_DOGS_COUNT; i++) + { + if ((FALSE == g_thread_dogs[i].alloc_flag) + && __sync_bool_compare_and_swap (&g_thread_dogs[i].alloc_flag, + FALSE, TRUE)) + { + t_val_idx = i; + break; + } + } + + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + g_thread_dogs[t_val_idx].count = 0; + g_thread_dogs[t_val_idx].thread_id = syscall (SYS_gettid); + } + + return TRUE; +} + +/***************************************************************** +Parameters : None +Return : +Description : +*****************************************************************/ +nsfw_thread_dogs * +nsfw_thread_getDog () +{ + u32 i; + nsfw_thread_dogs *retPtr = NULL; + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + return &g_thread_dogs[t_val_idx]; + } + + for (i = 1; i < NSFW_MAX_THREAD_DOGS_COUNT; i++) + { + if ((FALSE == g_thread_dogs[i].alloc_flag) + && __sync_bool_compare_and_swap (&g_thread_dogs[i].alloc_flag, + FALSE, TRUE)) + { + t_val_idx = i; + break; + } + } + + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + g_thread_dogs[t_val_idx].count = 0; + g_thread_dogs[t_val_idx].thread_id = syscall (SYS_gettid); + retPtr = &g_thread_dogs[t_val_idx]; + } + return retPtr; +} + +pthread_t g_all_thread[MAX_THREAD] = { 0 }; + +u8 +nsfw_reg_trace_thread (pthread_t tid) +{ + int i; + for (i = 0; i < MAX_THREAD; i++) + { + if ((0 == g_all_thread[i]) + && __sync_bool_compare_and_swap (&g_all_thread[i], 0, tid)) + { + return TRUE; + } + } + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_check_dst_init +* Description : send check msg check the dst process is listening +* Input : u8 dst_proc_type +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_check_dst_init (u8 dst_proc_type) +{ + u8 ps_state = FALSE; + nsfw_mgr_msg *msg = + nsfw_mgr_msg_alloc (MGR_MSG_CHK_INIT_REQ, dst_proc_type); + if (NULL == msg) + { + NSFW_LOGERR ("alloc msg failed]dst_typ=%d", dst_proc_type); + return FALSE; + } + + nsfw_ps_chk_msg *ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, msg); + ps_msg->ps_state = TRUE; + + nsfw_mgr_msg *rsp_msg = nsfw_mgr_null_rspmsg_alloc (); + if (NULL == rsp_msg) + { + nsfw_mgr_msg_free (msg); + NSFW_LOGERR ("alloc rsp msg failed]dst_typ=%d", dst_proc_type); + return FALSE; + } + + (void) nsfw_mgr_send_req_wait_rsp (msg, rsp_msg); + + ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, rsp_msg); + ps_state = ps_msg->ps_state; + + nsfw_mgr_msg_free (msg); + nsfw_mgr_msg_free (rsp_msg); + NSFW_LOGINF ("get peer state]dst_type=%d,state=%d", dst_proc_type, + ps_state); + return ps_state; +} + +/***************************************************************************** +* Prototype : nsfw_ps_send_hbt +* Description : seng heart beat message to peer +* Input : nsfw_ps_info* pps_info +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_send_hbt (nsfw_ps_info * pps_info) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("null ps_info!"); + return FALSE; + } + + nsfw_mgr_msg *req_msg = + nsfw_mgr_msg_alloc (MGR_MSG_CHK_HBT_REQ, pps_info->proc_type); + if (NULL == req_msg) + { + NSFW_LOGERR ("alloc req msg failed]pps_info=%p", pps_info); + return FALSE; + } + + req_msg->dst_pid = pps_info->host_pid; + nsfw_ps_chk_msg *ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, req_msg); + ps_msg->ps_state = TRUE; + u8 ret = nsfw_mgr_send_msg (req_msg); + nsfw_mgr_msg_free (req_msg); + NSFW_LOGDBG ("send hbt msg]ret=%d,pps_info=%p,pid=%d,type=%d", ret, + pps_info, pps_info->host_pid, pps_info->proc_type); + return ret; +} + +/***************************************************************************** +* Prototype : nsfw_ps_recv_hbt +* Description : recv heart beat message process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_recv_hbt (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("error msg nul!"); + return FALSE; + } + + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp failed,drop msg!" MSGINFO, PRTMSG (msg)); + return FALSE; + } + + nsfw_ps_chk_msg *ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, rsp_msg); + ps_msg->ps_state = TRUE; + ps_msg->thread_chk_count = nsfw_all_thread_chk (); + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_recv_hbt_rsp +* Description : recv heart beat response message process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_recv_hbt_rsp (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("error msg nul!"); + return FALSE; + } + + nsfw_ps_chk_msg *ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, msg); + if (TRUE != ps_msg->ps_state) + { + NSFW_LOGERR ("Heartbeat failed]pid=%u,type=%u", msg->src_pid, + msg->src_proc_type); + return FALSE; + } + + nsfw_ps_info *pps_info = nsfw_ps_info_get (msg->src_pid); + if (NULL == pps_info) + { + NSFW_LOGERR ("get ps_info failed]pid=%u,type=%u,count=%d", + msg->src_pid, msg->src_proc_type, + ps_msg->thread_chk_count); + return FALSE; + } + + if (0 == ps_msg->thread_chk_count) + { + pps_info->hbt_failed_count = 0; + return TRUE; + } + + if (pps_info->hbt_failed_count > (u32) ps_msg->thread_chk_count) + { + pps_info->hbt_failed_count = (u32) ps_msg->thread_chk_count; + } + + NSFW_LOGERR ("Heartbeat failed]pid=%u,type=%u,count=%d,ps_count=%u", + msg->src_pid, msg->src_proc_type, ps_msg->thread_chk_count, + pps_info->hbt_failed_count); + return FALSE; +} + +int +nsfw_ps_reset_hbt (void *pps_info, void *argv) +{ + nsfw_ps_info *ps_info = pps_info; + if (NULL == ps_info) + { + NSFW_LOGERR ("ps_info nul!"); + return FALSE; + } + + if (NSFW_PROC_MAIN != ps_info->proc_type) + { + return FALSE; + } + + ps_info->hbt_failed_count = *(u32 *) argv; + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_hbt_timeout +* Description : heart beat time out +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_hbt_timeout (u32 timer_type, void *data) +{ + nsfw_ps_info *pps_info = (nsfw_ps_info *) data; + + if (NULL == pps_info) + { + NSFW_LOGERR ("null ps_info!"); + return FALSE; + } + + if (NULL == pps_info->hbt_timer_ptr) + { + NSFW_LOGERR ("hbt has stop]pps_info=%p", pps_info); + pps_info->hbt_failed_count = 0; + return TRUE; + } + + if (TRUE == g_hbt_switch) + { + struct timespec time_left = { NSFW_CHK_HBT_TVLAUE, 0 }; + pps_info->hbt_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_CHK_HBT_TIMER, data, + nsfw_ps_hbt_timeout, time_left); + return TRUE; + } + + /* nic init may cost a few seconds, master will restart main if heartbeat timeout */ + if (NSFW_SOFT_HBT_CHK_COUNT != NSFW_MAX_HBT_CHK_COUNT) + { + if (NSFW_SOFT_HBT_CHK_COUNT < NSFW_MAX_HBT_CHK_COUNT) + { + u32 new_hbt_count = 0; + (void) nsfw_ps_iterator (nsfw_ps_reset_hbt, &new_hbt_count); + } + + NSFW_MAX_HBT_CHK_COUNT = NSFW_SOFT_HBT_CHK_COUNT; + } + + if (NSFW_MAX_HBT_CHK_COUNT <= pps_info->hbt_failed_count) + { + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_HBT_FAILED); + /*reset counter */ + pps_info->hbt_failed_count = 0; + } + + if (TRUE != nsfw_ps_send_hbt (pps_info)) + { + } + + if (pps_info->hbt_failed_count > 0) + { + NSFW_LOGWAR ("Heartbeat failed]pid=%u,ps_count=%u, max_count=%d", + pps_info->host_pid, pps_info->hbt_failed_count, + NSFW_MAX_HBT_CHK_COUNT); + } + + pps_info->hbt_failed_count++; + struct timespec time_left = { NSFW_CHK_HBT_TVLAUE, 0 }; + pps_info->hbt_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_CHK_HBT_TIMER, data, + nsfw_ps_hbt_timeout, time_left); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_hbt_start +* Description : start ps_info heart beat +* Input : nsfw_ps_info* pps_info +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_hbt_start (nsfw_ps_info * pps_info) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("null ps_info!"); + return FALSE; + } + + if (NULL != pps_info->hbt_timer_ptr) + { + NSFW_LOGERR ("hbt start before!]ps_info=%p,pid=%u,type=%u", pps_info, + pps_info->host_pid, pps_info->proc_type); + return FALSE; + } + + struct timespec time_left = { NSFW_CHK_HBT_TVLAUE, 0 }; + pps_info->hbt_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_CHK_HBT_TIMER, (void *) pps_info, + nsfw_ps_hbt_timeout, time_left); + NSFW_LOGINF ("hbt start!]ps_info=%p,pid=%u,type=%u", pps_info, + pps_info->host_pid, pps_info->proc_type); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_hbt_stop +* Description : stop ps_info heart beat +* Input : nsfw_ps_info* pps_info +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_hbt_stop (nsfw_ps_info * pps_info) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("null ps_info!"); + return FALSE; + } + + if (NULL != pps_info->hbt_timer_ptr) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) pps_info->hbt_timer_ptr); + pps_info->hbt_timer_ptr = NULL; + } + + NSFW_LOGINF ("hbt stop!]ps_info=%p,pid=%d,type=%d", pps_info, + pps_info->host_pid, pps_info->proc_type); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_iterator +* Description : get all ps_info process by fun +* Input : nsfw_ps_proc_fun fun +* void* argv +* Output : None +* Return Value : u32 +* Calls : +* Called By : +*****************************************************************************/ +u32 +nsfw_ps_iterator (nsfw_ps_proc_fun fun, void *argv) +{ + u32 count = 0; + nsfw_ps_info *pps_info = NULL; + struct list_head *tNode; + + if (NULL == fun) + { + NSFW_LOGERR ("fun null!"); + return count; + } + + LINT_LIST ()list_for_each_entry (pps_info, tNode, (&g_ps_runing_list), node) + { + (void) fun (pps_info, argv); + count++; + } + + NSFW_LOGINF ("proc pid]count=%u", count); + return count; +} + +int +filter (const struct dirent *dir) +{ + return !fnmatch ("[1-9]*", dir->d_name, 0); +} + +/***************************************************************************** +* Prototype : nsfw_ps_realloc_pid +* Description : realloc pid +* Input : u32 pid +* Output : None +* Return Value : inline nsfw_ps_info* +* Calls : +* Called By : +*****************************************************************************/ +inline nsfw_ps_info * +nsfw_ps_realloc_pid (u32 pid, u8 realloc_flg) +{ + nsfw_ps_info *pps_info = NULL; + if (pid >= NSFW_MAX_PID) + { + return NULL; + } + + if (g_ps_info[pid].ps_info == NULL) + { + return NULL; + } + + if (TRUE == realloc_flg) + { + pps_info = nsfw_ps_info_alloc (pid, g_ps_info[pid].proc_type); + if (NULL == pps_info) + { + NSFW_LOGERR ("alloc ps_info failed!]pid=%u,type=%u", pid, + g_ps_info[pid].proc_type); + return NULL; + } + } + else + { + pps_info = g_ps_info[pid].ps_info; + } + + pps_info->rechk_flg = TRUE; + return pps_info; +} + +/***************************************************************************** +* Prototype : nsfw_ps_reload_pid +* Description : reload pid +* Input : None +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_ps_reload_pid () +{ + struct dirent **namelist; + i32 n; + u32 host_pid; + nsfw_ps_info *pps_info = NULL; + + n = scandir ("/proc", &namelist, filter, 0); + if (n < 0) + { + NSFW_LOGERR ("buf null"); + } + else + { + while (n--) + { + host_pid = strtol (namelist[n]->d_name, NULL, 10); + pps_info = nsfw_ps_info_get (host_pid); + if (NULL != pps_info) + { + pps_info->rechk_flg = FALSE; + } + free (namelist[n]); + } + free (namelist); + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_ps_realloc_all_pid +* Description : realloc all pid +* Input : u32 *main_pid +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_ps_realloc_all_pid (u32 * main_pid, u8 realloc_flg) +{ + u32 i; + nsfw_ps_info *pps_info = NULL; + for (i = 0; i < NSFW_MAX_PID; i++) + { + pps_info = nsfw_ps_realloc_pid (i, realloc_flg); + if (NULL != main_pid) + { + if (NULL != pps_info && NSFW_PROC_MAIN == pps_info->proc_type) + { + (*main_pid) = i; + } + } + } +} + +/***************************************************************************** +* Prototype : nsfw_ps_chk_exit_timeout +* Description : chk ps info +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_chk_exit_timeout (u32 timer_type, void *data) +{ + u32 i; + nsfw_ps_info *pps_info = NULL; + u32 pid = (u64) data; + + /*main pid exit first */ + if (NULL != data) + { + pps_info = nsfw_ps_info_get (pid); + if (NULL != pps_info && TRUE == pps_info->rechk_flg) + { + if (NSFW_PS_EXITING != pps_info->state) + { + NSFW_LOGWAR ("rechk pid exit]ps_info=%p,pid=%u", pps_info, + pps_info->host_pid); + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXITING); + pps_info->rechk_flg = FALSE; + } + } + } + + for (i = 0; i < NSFW_MAX_PID; i++) + { + pps_info = nsfw_ps_info_get (i); + if (NULL != pps_info && TRUE == pps_info->rechk_flg) + { + if (NSFW_PS_EXITING == pps_info->state) + { + NSFW_LOGWAR ("double pid info]ps_info=%p,pid=%u", pps_info, + pps_info->host_pid); + continue; + } + + NSFW_LOGWAR ("rechk pid exit]ps_info=%p,pid=%u", pps_info, + pps_info->host_pid); + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXITING); + pps_info->rechk_flg = FALSE; + } + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_chk_timeout +* Description : load all running pid +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +****************************************************************************/ +int +nsfw_ps_chk_timeout (u32 timer_type, void *data) +{ + u32 main_pid = 0; + u8 realloc_flg = (u8) (u64) data; + + nsfw_ps_realloc_all_pid (&main_pid, realloc_flg); + nsfw_ps_reload_pid (); + + struct timespec time_left = { NSFW_PS_CHK_EXIT_TVLAUE, 0 }; + g_ps_chk_timer = + (void *) nsfw_timer_reg_timer (NSFW_PS_CHK_EXIT_TVLAUE, + (void *) (u64) main_pid, + nsfw_ps_chk_exit_timeout, time_left); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_rechk_pid_exit +* Description : rechck pid exit +* Input : nsfw_ps_proc_fun fun +* void* argv +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_rechk_pid_exit (nsfw_ps_pid_fun fun, void *argv) +{ + u32 ulI = 0; + if (NULL == fun) + { + NSFW_LOGERR ("input err! fun null"); + return -1; + } + + u8 *ps_pid = malloc (NSFW_MAX_PID); + if (NULL == ps_pid) + { + NSFW_LOGERR ("malloc failed"); + return -1; + } + + int retval = MEMSET_S (ps_pid, NSFW_MAX_PID, 0, NSFW_MAX_PID); + if (EOK != retval) + { + NSFW_LOGERR ("MEMSET_S failed]retval=%d", retval); + free (ps_pid); + return -1; + } + + struct dirent **namelist; + i32 n; + u32 host_pid; + n = scandir ("/proc", &namelist, filter, 0); + if (n < 0) + { + NSFW_LOGERR ("buf null"); + free (ps_pid); + return -1; + } + + while (n--) + { + host_pid = strtol (namelist[n]->d_name, NULL, 10); + if (host_pid < NSFW_MAX_PID) + { + ps_pid[ulI] = TRUE; + } + free (namelist[n]); + } + free (namelist); + + int count = 0; + for (ulI = 0; ulI < NSFW_MAX_PID; ulI++) + { + if ((NULL != g_master_ps_info[ulI].ps_info) && (FALSE == ps_pid[ulI])) + { + (void) fun (ulI, g_master_ps_info[ulI].proc_type, argv); + NSFW_LOGWAR ("rechk pid exit]pid=%d,type=%d", ulI, + g_master_ps_info[ulI].proc_type); + count++; + continue; + } + } + + free (ps_pid); + return count; +} + +void +nsfw_ps_cfg_set_chk_count (u16 count) +{ + g_ps_cfg.ps_chk_hbt_count = count; +} + +/***************************************************************************** +* Prototype : nsfw_ps_module_init +* Description : ps_module init +* Input : void* param +* Output : None +* Return Value : static int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_module_init (void *param) +{ + u32 proc_type = (u32) ((long long) param); + nsfw_ps_init_cfg *ps_cfg = &g_ps_cfg; + int retval; + nsfw_pid_item *pid_info = NULL; + NSFW_LOGINF ("ps module init]type=%u", proc_type); + + ps_cfg->ps_chk_hbt_count = NSFW_MAX_HBT_CHK_COUNT_DEF; + ps_cfg->ps_chk_hbt_tvalue = NSFW_CHK_HBT_TVLAUE_DEF; + ps_cfg->ps_chk_hbt_soft_count = ps_cfg->ps_chk_hbt_count; + + nsfw_mem_zone pzoneinfo; + pzoneinfo.isocket_id = NSFW_SOCKET_ANY; + pzoneinfo.stname.entype = NSFW_SHMEM; + pzoneinfo.lenth = sizeof (nsfw_pid_item) * NSFW_MAX_PID; + if (-1 == + SPRINTF_S (pzoneinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + "MAS_PS_INFO")) + { + NSFW_LOGERR ("SPRINTF_S failed]"); + return -1; + } + + switch (proc_type) + { + case NSFW_PROC_MASTER: + { + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_CHK_HBT_RSP, + nsfw_ps_recv_hbt_rsp); + (void) NSFW_REG_SOFT_INT (NSFW_HBT_TIMER, NSFW_CHK_HBT_TVLAUE, 1, + 0xFFFF); + (void) NSFW_REG_SOFT_INT (NSFW_HBT_COUNT_PARAM, + NSFW_SOFT_HBT_CHK_COUNT, 1, 0xFFFF); + (void) NSFW_REG_SOFT_INT (NSFW_APP_EXIT_TIMER, NSFW_PS_WEXIT_TVLAUE, + 1, 0xFFFF); + + pid_info = nsfw_mem_zone_lookup (&pzoneinfo.stname); + if (NULL == pid_info) + { + pid_info = nsfw_mem_zone_create (&pzoneinfo); + if (NULL == pid_info) + { + NSFW_LOGERR ("alloc rec nul!"); + return -1; + } + + retval = + MEMSET_S (pid_info, (sizeof (nsfw_pid_item) * NSFW_MAX_PID), + 0, (sizeof (nsfw_pid_item) * NSFW_MAX_PID)); + if (EOK != retval) + { + NSFW_LOGERR ("MEMSET_S failed]retval=%d.\n", retval); + return -1; + } + } + + MEM_STAT (NSFW_PS_MODULE, pzoneinfo.stname.aname, NSFW_SHMEM, + pzoneinfo.lenth); + g_ps_info = pid_info; + break; + } + case NSFW_PROC_MAIN: + { + pid_info = malloc (sizeof (nsfw_pid_item) * NSFW_MAX_PID); + if (NULL == pid_info) + { + NSFW_LOGERR ("malloc mem failed!"); + return -1; + } + + retval = + MEMSET_S (pid_info, (sizeof (nsfw_pid_item) * NSFW_MAX_PID), 0, + (sizeof (nsfw_pid_item) * NSFW_MAX_PID)); + if (EOK != retval) + { + NSFW_LOGERR ("MEMSET_S failed]retval=%d.\n", retval); + free (pid_info); + return -1; + } + + g_ps_info = pid_info; + + pzoneinfo.stname.enowner = NSFW_PROC_MAIN; + pid_info = nsfw_mem_zone_create (&pzoneinfo); + if (NULL == pid_info) + { + NSFW_LOGERR ("create pid_info failed!"); + return -1; + } + + g_master_ps_info = pid_info; + break; + } + default: + return 0; + } + + ps_cfg->ps_info_size = NSFW_PS_INFO_MAX_COUNT; + ps_cfg->ps_waite_exit_tvalue = NSFW_PS_WEXIT_TVLAUE_DEF; + ps_cfg->net_link_buf = MAX_NET_LINK_BUF_DEF; + + INIT_LIST_HEAD (&(g_ps_runing_list)); + + nsfw_mem_sppool pmpinfo; + pmpinfo.enmptype = NSFW_MRING_MPMC; + pmpinfo.usnum = ps_cfg->ps_info_size; + pmpinfo.useltsize = sizeof (nsfw_ps_info); + pmpinfo.isocket_id = NSFW_SOCKET_ANY; + pmpinfo.stname.entype = NSFW_NSHMEM; + if (-1 == + SPRINTF_S (pmpinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + "MAS_PS_INFOPOOL")) + { + NSFW_LOGERR ("SPRINTF_S failed]"); + return -1; + } + + ps_cfg->ps_info_pool = nsfw_mem_sp_create (&pmpinfo); + + if (!ps_cfg->ps_info_pool) + { + NSFW_LOGERR ("alloc ps info pool_err"); + return -1; + } + + MEM_STAT (NSFW_PS_MODULE, pmpinfo.stname.aname, NSFW_NSHMEM, + nsfw_mem_get_len (ps_cfg->ps_info_pool, NSFW_MEM_SPOOL)); + + if (NSFW_PROC_MASTER != proc_type) + { + return 0; + } + + struct timespec time_left = { NSFW_PS_FIRST_CHK_TVLAUE, 0 }; + g_ps_chk_timer = + (void *) nsfw_timer_reg_timer (NSFW_PS_CHK_TIMER, (void *) TRUE, + nsfw_ps_chk_timeout, time_left); + + if (TRUE != nsfw_ps_start_netlink ()) + { + return -1; + } + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_PS_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_MGR_COM_MODULE) +NSFW_MODULE_DEPENDS (NSFW_TIMER_MODULE) +NSFW_MODULE_INIT (nsfw_ps_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/ps/nsfw_ps_module.h b/src/framework/ipc/ps/nsfw_ps_module.h new file mode 100644 index 0000000..b754cea --- /dev/null +++ b/src/framework/ipc/ps/nsfw_ps_module.h @@ -0,0 +1,99 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_PS_MODULE_H +#define _NSFW_PS_MODULE_H + +#include "nsfw_ps_api.h" +#include "nsfw_mem_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ + +#define NSFW_MAX_PID 65535 +COMPAT_PROTECT (NSFW_MAX_PID, 65535); + +#define NSFW_PS_INFO_MAX_COUNT 4095 +#define MAX_NET_LINK_BUF_DEF 0x34000*32 + +#define NSFW_PS_WEXIT_TIMER 1 +#define NSFW_PS_WEXIT_TVLAUE_DEF 180 + +#define NSFW_PS_WEXIT_TVLAUE (g_ps_cfg.ps_waite_exit_tvalue) +#define MAX_NET_LINK_BUF (g_ps_cfg.net_link_buf) + +typedef struct _nsfw_ps_init_cfg +{ + u32 ps_info_size; + u32 net_link_buf; + + u16 ps_waite_exit_tvalue; + u16 ps_chk_hbt_count; + u16 ps_chk_hbt_soft_count; + u16 ps_chk_hbt_tvalue; + + mring_handle ps_info_pool; +} nsfw_ps_init_cfg; + +#define NSFW_PS_CHK_TIMER 1 +#define NSFW_PS_FIRST_CHK_TVLAUE 1 +#define NSFW_PS_CHK_EXIT_TVLAUE 1 + +typedef struct _nsfw_pid_item +{ + u8 proc_type; + u8 u8_reserve; + u16 u16_reserve; + u32 u32_reserve; + nsfw_ps_info *ps_info; +} nsfw_pid_item; + +int nsfw_ps_change_fun (i32 epfd, i32 socket, u32 events); +u8 nsfw_sw_ps_state (nsfw_ps_info * pps_info, u8 new_state); + +/* for heartbeat checking*/ +#define NSFW_MAX_THREAD_DOGS_COUNT 8 +#define NSFW_CHK_HBT_TIMER 1 +#define NSFW_MAX_HBT_PROC_FUN 4 + +#define NSFW_CHK_HBT_TVLAUE_DEF 1 + +#define NSFW_MAX_HBT_CHK_COUNT (g_ps_cfg.ps_chk_hbt_count) +#define NSFW_SOFT_HBT_CHK_COUNT (g_ps_cfg.ps_chk_hbt_soft_count) +#define NSFW_CHK_HBT_TVLAUE (g_ps_cfg.ps_chk_hbt_tvalue) + +typedef struct _nsfw_ps_chk_msg +{ + u32 ps_state; + i32 thread_chk_count; +} nsfw_ps_chk_msg; + +int nsfw_ps_chk_timeout (u32 timer_type, void *data); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_PS_MODULE_H */ diff --git a/src/framework/ipc/ps/nsfw_recycle_module.c b/src/framework/ipc/ps/nsfw_recycle_module.c new file mode 100644 index 0000000..bb3844f --- /dev/null +++ b/src/framework/ipc/ps/nsfw_recycle_module.c @@ -0,0 +1,666 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nsfw_mgr_com_api.h" +#include "nsfw_mem_api.h" +#include "nsfw_ps_api.h" +#include "nsfw_ps_mem_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_recycle_module.h" +#include "nsfw_maintain_api.h" +#include "nstack_log.h" +#include "common_mem_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +/* only work on nStackMain*/ +nsfw_recycle_cfg g_rec_cfg; + +nsfw_recycle_fun g_rec_fun[NSFW_REC_TYPE_MAX] = { 0 }; + +nsfw_rec_fun_info g_rec_lock_fun[NSFW_REC_LOCK_REL_MAX_FUN]; + +/***************************************************************************** +* Prototype : nsfw_recycle_reg_fun +* Description : reg one recycle type recycle funciton +* Input : u16 rec_type +* nsfw_recycle_fun fun +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_reg_fun (u16 rec_type, nsfw_recycle_fun fun) +{ + if (NULL == fun || rec_type >= NSFW_REC_TYPE_MAX) + { + NSFW_LOGERR ("argv err]fun=%p,type=%u", fun, rec_type); + return FALSE; + } + + g_rec_fun[rec_type] = fun; + NSFW_LOGINF ("reg]fun=%d,type=%u", fun, rec_type); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_lock_rel_fun +* Description : reg lock release when app exit run +* Input : nsfw_recycle_fun fun +* void* data +* u8 proc_type: NULL as all +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_lock_rel_fun (nsfw_recycle_fun fun, void *data, u8 proc_type) +{ + if (NULL == fun) + { + NSFW_LOGERR ("argv err]fun=%p,data=%p", fun, data); + return FALSE; + } + + u32 i; + + for (i = 0; i < NSFW_REC_LOCK_REL_MAX_FUN; i++) + { + if (NULL == g_rec_lock_fun[i].rec_fun) + { + g_rec_lock_fun[i].rec_fun = fun; + g_rec_lock_fun[i].data = data; + g_rec_lock_fun[i].proc_type = proc_type; + NSFW_LOGINF ("reg mgr_msg fun suc]fun=%p,data=%p", fun, data); + return TRUE; + } + } + + NSFW_LOGINF ("reg]fun=%p,data=%p", fun, data); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_exit_pid_lock +* Description : release all lock fun +* Input : u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_recycle_exit_pid_lock (u32 pid, u8 proc_type, void *argv) +{ + u32 i; + NSFW_LOGINF ("release lock]pid=%d,type=%d", pid, proc_type); + for (i = 0; i < NSFW_REC_LOCK_REL_MAX_FUN; i++) + { + if (NULL == g_rec_lock_fun[i].rec_fun) + { + break; + } + + if ((NSFW_PROC_NULL == g_rec_lock_fun[i].proc_type) + || (proc_type == g_rec_lock_fun[i].proc_type)) + { + (void) g_rec_lock_fun[i].rec_fun (pid, g_rec_lock_fun[i].data, 0); + } + } + + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_obj_end +* Description : one recycle object process finished notify +* Input : u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_obj_end (u32 pid) +{ + nsfw_mgr_msg *rsp_msg = + nsfw_mgr_msg_alloc (MGR_MSG_RCC_END_REQ, NSFW_PROC_MAIN); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp msg failed]pid=%u", pid); + return FALSE; + } + + nsfw_ps_info_msg *ps_msg = GET_USER_MSG (nsfw_ps_info_msg, rsp_msg); + ps_msg->host_pid = pid; + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + NSFW_LOGINF ("send obj end msg]pid=%d", pid); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_callback_all_obj +* Description : process all recycle object +* Input : u32 pid +* nsfw_recycle_pool *rec_pool +* Output : None +* Return Value : nsfw_rcc_stat +* Calls : +* Called By : +*****************************************************************************/ +nsfw_rcc_stat +nsfw_recycle_callback_all_obj (u32 pid, nsfw_recycle_pool * rec_pool) +{ + u32 match = 0; + nsfw_recycle_obj *obj = NULL; + if (NULL == rec_pool) + { + return NSFW_RCC_CONTINUE; + } + + nsfw_recycle_obj *p_start = rec_pool->obj; + u32 i; + u32 size = rec_pool->pool_size; + + nsfw_ps_info *pps_info; + pps_info = nsfw_ps_info_get (pid); + if (NULL == pps_info) + { + NSFW_LOGERR ("get ps_info falied!]pid=%d", pid); + return NSFW_RCC_CONTINUE; + } + + i32 cur_idx = (i32) (u64) nsfw_ps_get_uv (pps_info, NSFW_REC_IDX); + + if (-1 == cur_idx) + { + cur_idx = 0; + nsfw_ps_set_uv (pps_info, NSFW_REC_IDX, (void *) (u64) cur_idx); + (void) nsfw_recycle_exit_pid_lock (pid, NSFW_PROC_APP, NULL); + } + else + { + cur_idx++; + nsfw_ps_set_uv (pps_info, NSFW_REC_IDX, (void *) (u64) cur_idx); + } + + for (i = cur_idx; i < size; i++) + { + obj = &p_start[i]; + cur_idx = i; + nsfw_ps_set_uv (pps_info, NSFW_REC_IDX, (void *) (u64) cur_idx); + if (FALSE == obj->alloc_flag) + { + continue; + } + + if ((obj->rec_type < NSFW_REC_TYPE_MAX) + && (NULL != g_rec_fun[obj->rec_type])) + { + match++; + if (NSFW_RCC_SUSPEND == + g_rec_fun[obj->rec_type] (pid, obj->data, obj->rec_type)) + { + NSFW_LOGINF + ("call suspend]type=%d,obj_pid=%d,pid=%d,count=%d", + obj->rec_type, obj->host_pid, pid, match); + return NSFW_RCC_SUSPEND; + } + } + else + { + NSFW_LOGERR ("obj_error!drop]type=%d,obj_pid=%d,pid=%d", + obj->rec_type, obj->host_pid, pid); + } + } + + NSFW_LOGWAR ("rec obj]pid=%d,count=%d,cur_idx=%d", pid, match, cur_idx); + return NSFW_RCC_CONTINUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_pid_obj +* Description : recycle object with pid +* Input : u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_pid_obj (u32 pid) +{ + nsfw_ps_info *pps_info; + pps_info = nsfw_ps_info_get (pid); + if (NULL == pps_info) + { + NSFW_LOGERR ("get ps_info falied!]pid=%d", pid); + return FALSE; + } + + nsfw_recycle_pool *rec_pool = g_rec_cfg.mem_rec_obj_pool; + void *timer_ptr = nsfw_ps_get_uv (pps_info, NSFW_REC_TIMER); + if (NSFW_RCC_SUSPEND == nsfw_recycle_callback_all_obj (pid, rec_pool)) + { + if (NULL != timer_ptr) + { + nsfw_timer_rmv_timer (timer_ptr); + timer_ptr = NULL; + } + + struct timespec time_left = { NSFW_REC_WEND_TVLAUE, 0 }; + timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_REC_WEND_TIMER, + (void *) (u64) pid, + nsfw_recycle_obj_timeout, time_left); + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, timer_ptr); + return TRUE; + } + + if (NULL != timer_ptr) + { + nsfw_timer_rmv_timer (timer_ptr); + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, NULL); + } + + (void) nsfw_ps_exit_end_notify (pid); + nsfw_ps_info_free (pps_info); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_all_obj +* Description : +* Input : u32 pid +* nsfw_mem_addr_msg *addr_msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_all_obj (u32 pid) +{ + nsfw_ps_info *pps_info; + pps_info = nsfw_ps_info_get (pid); + if (NULL == pps_info) + { + pps_info = nsfw_ps_info_alloc (pid, NSFW_PROC_APP); + if (NULL == pps_info) + { + NSFW_LOGERR ("alloc ps_info falied!]pid=%u", pid); + return FALSE; + } + } + + nsfw_ps_set_uv (pps_info, NSFW_REC_IDX, (void *) (-1)); + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, NULL); + return nsfw_recycle_pid_obj (pid); +} + +/***************************************************************************** +* Prototype : mem_app_exit_proc +* Description : exiting message process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_app_exit_proc (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("msg nul"); + return FALSE; + } + + nsfw_ps_info_msg *ps_info_msg = GET_USER_MSG (nsfw_ps_info_msg, msg); + + /* look up the app rec memzone and release all resource */ + /* no need to send rsp for it will be send after stack process over */ + if (TRUE == nsfw_recycle_all_obj (ps_info_msg->host_pid)) + { + NSFW_LOGINF ("obj found!]pid=%d", ps_info_msg->host_pid); + return TRUE; + } + + (void) nsfw_ps_exit_end_notify (ps_info_msg->host_pid); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_obj_end_proc +* Description : obj recycle finished notify process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_recycle_obj_end_proc (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("msg nul"); + return FALSE; + } + + nsfw_ps_info_msg *ps_info_msg = GET_USER_MSG (nsfw_ps_info_msg, msg); + + return nsfw_recycle_pid_obj (ps_info_msg->host_pid); +} + +/***************************************************************************** +* Prototype : nsfw_recycle_obj_timeout +* Description : recycle object timeout process +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_recycle_obj_timeout (u32 timer_type, void *data) +{ + u32 pid = (u64) data; + void *timer_ptr = NULL; + NSFW_LOGINF ("ps_info timerout]pid=%u", pid); + + nsfw_ps_info *pps_info; + pps_info = nsfw_ps_info_get (pid); + if (NULL != pps_info) + { + nsfw_recycle_pool *rec_pool = g_rec_cfg.mem_rec_obj_pool; + if (NULL != rec_pool) + { + if (TRUE == g_hbt_switch) + { + struct timespec time_left = { NSFW_REC_WEND_TVLAUE, 0 }; + timer_ptr = + (void *) nsfw_timer_reg_timer (timer_type, data, + nsfw_recycle_obj_timeout, + time_left); + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, timer_ptr); + return TRUE; + } + } + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, timer_ptr); + } + + (void) nsfw_recycle_pid_obj (pid); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_rec_zone_init +* Description : init recycle zone in app, only work on App +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_rec_zone_init () +{ + nsfw_mem_mring pringinfo; + pringinfo.enmptype = NSFW_MRING_MPMC; + pringinfo.isocket_id = NSFW_SOCKET_ANY; + pringinfo.stname.entype = NSFW_NSHMEM; + pringinfo.usnum = MEM_RECYCLE_PER_PRO_QUE; + u32 i; + for (i = 0; i < NSFW_REC_PRO_MAX; i++) + { + if (-1 == + SPRINTF_S (pringinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s%d", + MEM_REC_QUEUE_NAME, i)) + { + NSFW_LOGERR ("SPRINTF_S failed]"); + return FALSE; + } + g_rec_cfg.mem_rec_pro[i] = nsfw_mem_ring_create (&pringinfo); + if (NULL == g_rec_cfg.mem_rec_pro[i]) + { + NSFW_LOGERR ("alloc rec ring nul!"); + return FALSE; + } + } + + MEM_STAT (NSFW_RECYCLE_MODULE, MEM_REC_QUEUE_NAME, NSFW_NSHMEM, + NSFW_REC_PRO_MAX * nsfw_mem_get_len (g_rec_cfg.mem_rec_pro[0], + NSFW_MEM_RING)); + + nsfw_mem_zone pzoneinfo; + pzoneinfo.isocket_id = NSFW_SOCKET_ANY; + pzoneinfo.stname.entype = NSFW_NSHMEM; + pzoneinfo.lenth = + MEM_RECYCLE_OBJ_MAX_NUM * sizeof (nsfw_recycle_obj) + + sizeof (nsfw_recycle_pool); + if (-1 == + SPRINTF_S (pzoneinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + MEM_REC_POOL_NAME)) + { + NSFW_LOGERR ("SPRINTF_S failed]"); + return FALSE; + } + + g_rec_cfg.mem_rec_obj_pool = nsfw_mem_zone_create (&pzoneinfo); + if (NULL == g_rec_cfg.mem_rec_obj_pool) + { + NSFW_LOGERR ("alloc rec pool nul!"); + return FALSE; + } + + MEM_STAT (NSFW_RECYCLE_MODULE, MEM_REC_POOL_NAME, NSFW_NSHMEM, + pzoneinfo.lenth); + + int retval; + retval = + MEMSET_S (g_rec_cfg.mem_rec_obj_pool, pzoneinfo.lenth, 0, + pzoneinfo.lenth); + if (EOK != retval) + { + NSFW_LOGERR ("mem set init failed!"); + return FALSE; + } + + i32 j; + nsfw_recycle_pool *rec_pool = + (nsfw_recycle_pool *) g_rec_cfg.mem_rec_obj_pool; + rec_pool->pool_size = MEM_RECYCLE_OBJ_MAX_NUM; + + nsfw_recycle_obj *p_start = rec_pool->obj; + for (i = 0; i < NSFW_REC_PRO_MAX; i++) + { + for (j = 0; j < MEM_RECYCLE_PER_PRO_QUE; j++) + { + if (FALSE == p_start[j].alloc_flag) + { + if (0 == + nsfw_mem_ring_enqueue (g_rec_cfg.mem_rec_pro[i], + &p_start[j])) + { + NSFW_LOGERR ("enqueue failed"); + break; + } + } + } + p_start = p_start + MEM_RECYCLE_PER_PRO_QUE; + } + + NSFW_LOGINF ("init rec pool and ring suc!"); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_reg_obj +* Description : reg one recycle object +* Input : u8 priority +* u16 rec_type +* void* data +* Output : None +* Return Value : void * +* Calls : +* Called By : +*****************************************************************************/ +void * +nsfw_recycle_reg_obj (u8 priority, u16 rec_type, void *data) +{ + if (NSFW_REC_PRO_MAX <= priority) + { + NSFW_LOGERR ("pro error]priority=%d,rec_type=%d,data=%p", priority, + rec_type, data); + return NULL; + } + + nsfw_recycle_obj *obj = NULL; + if (0 == + nsfw_mem_ring_dequeue (g_rec_cfg.mem_rec_pro[priority], (void *) &obj)) + { + NSFW_LOGERR ("dequeue error]priority=%d,rec_type=%d,data=%p", + priority, rec_type, data); + return NULL; + } + + if (EOK != MEMSET_S (obj, sizeof (*obj), 0, sizeof (*obj))) + { + if (0 == nsfw_mem_ring_enqueue (g_rec_cfg.mem_rec_pro[priority], obj)) + { + NSFW_LOGERR ("enqueue error]priority=%d,rec_type=%d,data=%p", + priority, rec_type, data); + } + + NSFW_LOGERR ("mem set error]priority=%d,rec_type=%d,data=%p", + priority, rec_type, data); + return NULL; + } + + obj->alloc_flag = TRUE; + obj->rec_type = rec_type; + obj->data = data; + obj->host_pid = get_sys_pid (); + obj->alloc_flag = TRUE; + NSFW_LOGINF ("en queue obj]priority=%d,rec_type=%d,data=%p", priority, + rec_type, data); + return obj; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_rechk_lock +* Description : add for rechk lock +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_recycle_rechk_lock () +{ + return nsfw_ps_rechk_pid_exit (nsfw_recycle_exit_pid_lock, NULL); +} + +/***************************************************************************** +* Prototype : nsfw_recycle_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : static int +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC int nsfw_recycle_module_init (void *param); +NSTACK_STATIC int +nsfw_recycle_module_init (void *param) +{ + u32 proc_type = (u32) ((long long) param); + NSFW_LOGINF ("recycle module init]type=%d", proc_type); + g_rec_cfg.rec_waite_end_tvalue = NSFW_REC_WEND_TVLAUE_DEF; + switch (proc_type) + { + case NSFW_PROC_MASTER: + return 0; + case NSFW_PROC_MAIN: + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_APP_EXIT_REQ, mem_app_exit_proc); + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_RCC_END_REQ, + nsfw_recycle_obj_end_proc); + if (TRUE == mem_rec_zone_init ()) + { + return 0; + } + + return 0; + default: + if (proc_type < NSFW_PROC_MAX) + { + break; + } + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_fork_init +* Description : fork init +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_fork_init () +{ + /* reconnect to master after fork in child proc */ + nsfw_mgr_close_dst_proc (NSFW_PROC_MAIN, 0); + nsfw_mgr_close_dst_proc (NSFW_PROC_MASTER, 0); + if (0 == nsfw_recycle_module_init ((void *) ((long long) NSFW_PROC_APP))) + { + return TRUE; + } + return FALSE; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_RECYCLE_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_PS_MEM_MODULE) +NSFW_MODULE_INIT (nsfw_recycle_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/ps/nsfw_recycle_module.h b/src/framework/ipc/ps/nsfw_recycle_module.h new file mode 100644 index 0000000..694c1d2 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_recycle_module.h @@ -0,0 +1,84 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_RECYCLE_MODULE_H +#define _NSFW_RECYCLE_MODULE_H + +#include "nsfw_recycle_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define MEM_RECYCLE_PER_PRO_QUE 128 +#define MEM_RECYCLE_OBJ_MAX_NUM (MEM_RECYCLE_PER_PRO_QUE*NSFW_REC_PRO_MAX) + +#define MEM_REC_POOL_NAME "APP_REC_POOL" +#define MEM_REC_QUEUE_NAME "APP_REC_RINGQ" + +#define REC_POOL_MAGIC_FLAG 0xDBFC01A600000000 + +#define NSFW_REC_WEND_TIMER 1 +#define NSFW_REC_WEND_TVLAUE_DEF 60 + +#define NSFW_REC_WEND_TVLAUE (g_rec_cfg.rec_waite_end_tvalue) + +typedef struct _nsfw_recycle_obj +{ + u8 alloc_flag; + u8 u8reserve; + u16 rec_type; + u32 host_pid; + void *data; + u64 u64reserve; +} nsfw_recycle_obj; + +#define NSFW_REC_LOCK_REL_MAX_FUN 32 + +typedef struct _nsfw_rec_fun_info +{ + nsfw_recycle_fun rec_fun; + void *data; + u8 proc_type; +} nsfw_rec_fun_info; + +typedef struct _nsfw_recycle_pool +{ + u32 pool_size; + nsfw_recycle_obj obj[0]; +} nsfw_recycle_pool; + +typedef struct _nsfw_recycle_cfg +{ + u16 rec_waite_end_tvalue; + mring_handle mem_rec_obj_pool; + mzone_handle mem_rec_pro[NSFW_REC_PRO_MAX]; +} nsfw_recycle_cfg; + +extern nsfw_rcc_stat nsfw_recycle_callback_all_obj (u32 pid, + nsfw_recycle_pool * + rec_pool); +extern int nsfw_recycle_obj_timeout (u32 timer_type, void *data); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_RECYCLE_MODULE_H */ diff --git a/src/framework/ipc/ps/nsfw_soft_param.c b/src/framework/ipc/ps/nsfw_soft_param.c new file mode 100644 index 0000000..d458040 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_soft_param.c @@ -0,0 +1,296 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nstack_log.h" +#include "nsfw_maintain_api.h" + +#include "nsfw_mem_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +typedef struct _nsfw_set_soft_item +{ + void *data; + u32 size; + u64 max; + u64 min; +} nsfw_set_soft_item; + +/* *INDENT-OFF* */ +nsfw_set_soft_fun g_soft_fun[NSFW_MAX_SOFT_PARAM] = { 0 }; +nsfw_set_soft_item g_soft_int_cfg[NSFW_MAX_SOFT_PARAM]; +/* *INDENT-ON* */ + +int +nsfw_isdigitstr (const char *str) +{ + if (NULL == str || '\0' == str[0]) + return 0; + + while (*str) + { + if (*str < '0' || *str > '9') + return 0; + str++; + } + return 1; +} + +u8 +nsfw_soft_param_reg_fun (u32 param_name, nsfw_set_soft_fun fun) +{ + if (NULL == fun || param_name >= NSFW_MAX_SOFT_PARAM) + { + NSFW_LOGERR ("argv err]fun=%p,type=%u", fun, param_name); + return FALSE; + } + + g_soft_fun[param_name] = fun; + NSFW_LOGINF ("reg]fun=%d,type=%u", fun, param_name); + return TRUE; +} + +int +nsfw_soft_set_int (u32 param, char *buf, u32 buf_len) +{ + u64 buf_value = 0; + if (NULL == buf || param >= NSFW_MAX_SOFT_PARAM) + { + NSFW_LOGERR ("argv err]buf=%p,param=%u", buf, param); + return FALSE; + } + + if (!nsfw_isdigitstr (buf)) + { + NSFW_LOGERR ("argv err]buf=%s,param=%u", buf, param); + return FALSE; + } + + char *parsing_end; + buf_value = (u64) strtol (buf, &parsing_end, 10); + nsfw_set_soft_item *int_item = &g_soft_int_cfg[param]; + if (NULL == int_item->data) + { + NSFW_LOGERR ("data err]buf=%s,param=%u,min=%llu,max=%llu", buf, param, int_item->min, int_item->max); //[DTS2017112402499][2017-11-24][z00316269] Issue #40, fix type dismatch + return FALSE; + } + + if (buf_value < int_item->min || buf_value > int_item->max) + { + NSFW_LOGERR ("argv err]buf=%s,param=%u,min=%llu,max=%llu", buf, param, int_item->min, int_item->max); //[DTS2017112402499][2017-11-24][z00316269] Issue #40, fix type dismatch + return FALSE; + } + + u32 size = int_item->size; + if (size >= sizeof (u64)) + { + size = sizeof (u64); + } + + if (EOK != MEMCPY_S (int_item->data, size, &buf_value, size)) + { + NSFW_LOGERR ("MEMCPY_S failed"); + return FALSE; + } + + NSFW_LOGINF ("set soft param ok]param=%u,value=%llu,size=%u", param, + buf_value, size); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_soft_param_reg_int +* Description : reg int param set +* Input : u32 param_name +* u32 size +* u32 min +* u32 max +* u64 *data +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_soft_param_reg_int (u32 param_name, u32 size, u32 min, u32 max, + u64 * data) +{ + if (NULL == data || param_name >= NSFW_MAX_SOFT_PARAM) + { + NSFW_LOGERR ("argv err]data=%p,type=%u", data, param_name); + return FALSE; + } + + g_soft_int_cfg[param_name].data = data; + g_soft_int_cfg[param_name].size = size; + g_soft_int_cfg[param_name].max = max; + g_soft_int_cfg[param_name].min = min; + return nsfw_soft_param_reg_fun (param_name, nsfw_soft_set_int); +} + +void +nsfw_set_soft_para (fw_poc_type proc_type, u32 para_name, void *value, + u32 size) +{ + nsfw_mgr_msg *msg = + (nsfw_mgr_msg *) nsfw_mgr_msg_alloc (MGR_MSG_SOF_PAR_REQ, proc_type); + if (NULL == msg) + { + NSFW_LOGERR + ("nsfw_mgr_msg_alloc failed] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + return; + } + + nsfw_soft_param_msg *soft_msg = GET_USER_MSG (nsfw_soft_param_msg, msg); + + soft_msg->param_name = para_name; + soft_msg->rsp_code = 0; + + if (EOK != + MEMCPY_S (soft_msg->param_value, sizeof (soft_msg->param_value), + value, size)) + { + NSFW_LOGERR + ("MEMCPY_S failed] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + nsfw_mgr_msg_free (msg); + return; + } + + nsfw_mgr_msg *rsp = nsfw_mgr_null_rspmsg_alloc (); + if (NULL == rsp) + { + NSFW_LOGERR + ("nsfw_mgr_null_rspmsg_alloc failed] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + nsfw_mgr_msg_free (msg); + return; + } + + if (!nsfw_mgr_send_req_wait_rsp (msg, rsp)) + { + NSFW_LOGERR + ("can not get response] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + nsfw_mgr_msg_free (msg); + nsfw_mgr_msg_free (rsp); + return; + } + + nsfw_soft_param_msg *soft_rsp_msg = GET_USER_MSG (nsfw_soft_param_msg, rsp); + if (soft_rsp_msg->rsp_code != NSFW_EXIT_SUCCESS) + { + NSFW_LOGERR + ("set soft param failed] msg type=%d, proc type=%d, para_name=%u, rsp code=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name, soft_rsp_msg->rsp_code); + nsfw_mgr_msg_free (msg); + nsfw_mgr_msg_free (rsp); + return; + } + + NSFW_LOGINF + ("set soft param success] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + + nsfw_mgr_msg_free (msg); + nsfw_mgr_msg_free (rsp); + return; +} + +int +nsfw_softparam_msg_proc (nsfw_mgr_msg * msg) +{ + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp failed,drop msg!" MSGINFO, PRTMSG (msg)); + return FALSE; + } + + nsfw_soft_param_msg *soft_msg = GET_USER_MSG (nsfw_soft_param_msg, msg); + nsfw_soft_param_msg *soft_rsp_msg = + GET_USER_MSG (nsfw_soft_param_msg, rsp_msg); + if ((soft_msg->param_name < NSFW_MAX_SOFT_PARAM) + && (NULL != g_soft_fun[soft_msg->param_name])) + { + soft_msg->param_value[sizeof (soft_msg->param_value) - 1] = 0; + (void) g_soft_fun[soft_msg->param_name] (soft_msg->param_name, + (char *) + soft_msg->param_value, + sizeof + (soft_msg->param_value)); + soft_rsp_msg->rsp_code = NSFW_EXIT_SUCCESS; + } + else + { + NSFW_LOGERR ("set soft failed!]soft=%u", soft_msg->param_name); + soft_rsp_msg->rsp_code = NSFW_EXIT_FAILED; + } + + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + return TRUE; +} + +int nsfw_softparam_module_init (void *param); +int +nsfw_softparam_module_init (void *param) +{ + u8 proc_type = (u8) ((long long) param); + NSFW_LOGINF ("softparam module init]type=%u", proc_type); + switch (proc_type) + { + case NSFW_PROC_MAIN: + case NSFW_PROC_MASTER: + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_SOF_PAR_REQ, + nsfw_softparam_msg_proc); + return 0; + default: + if (proc_type < NSFW_PROC_MAX) + { + break; + } + return -1; + } + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_SOFT_PARAM_MODULE) +NSFW_MODULE_PRIORITY (99) +NSFW_MODULE_INIT (nsfw_softparam_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ |