From c398e6ec613c1f90ffe33608c511208100e7372f Mon Sep 17 00:00:00 2001 From: Yalei Wang Date: Mon, 12 Mar 2018 10:07:58 +0800 Subject: Add the nSocket module for dmm Change-Id: I8b97fbe50c9c1c479072510b8d799fe711360da7 Signed-off-by: Yalei Wang --- src/nSocket/CMakeLists.txt | 51 + src/nSocket/include/declare_syscalls.h | 51 + src/nSocket/include/nstack_atomic.h | 57 + src/nSocket/include/nstack_dmm_api.h | 92 + src/nSocket/include/nstack_eventpoll.h | 338 +++ src/nSocket/include/nstack_ip_addr.h | 36 + src/nSocket/include/nstack_rd.h | 47 + src/nSocket/include/nstack_rd_init.h | 45 + src/nSocket/include/nstack_select.h | 153 ++ src/nSocket/include/nstack_sockops.h | 55 + src/nSocket/include/nstack_types.h | 152 ++ src/nSocket/include/select_adapt.h | 105 + src/nSocket/kernel/linux_kernel_module.c | 337 +++ src/nSocket/kernel/linux_kernel_module.h | 61 + src/nSocket/kernel/linux_kernel_socket.c | 64 + src/nSocket/kernel/linux_kernel_socket.h | 36 + src/nSocket/nstack/event/epoll/nstack_eventpoll.c | 1213 +++++++++ src/nSocket/nstack/event/select/nstack_select.c | 756 ++++++ src/nSocket/nstack/event/select/select_adapt.c | 339 +++ src/nSocket/nstack/nstack.c | 833 ++++++ src/nSocket/nstack/nstack.h | 121 + src/nSocket/nstack/nstack_fd_mng.c | 240 ++ src/nSocket/nstack/nstack_fd_mng.h | 210 ++ src/nSocket/nstack/nstack_info_parse.c | 493 ++++ src/nSocket/nstack/nstack_info_parse.h | 56 + src/nSocket/nstack/nstack_module.c | 269 ++ src/nSocket/nstack/nstack_module.h | 157 ++ src/nSocket/nstack/nstack_nsocket_construct.c | 43 + src/nSocket/nstack/nstack_socket.c | 2816 +++++++++++++++++++++ src/nSocket/nstack/nstack_socket.h | 231 ++ src/nSocket/nstack_rd/nstack_rd.c | 386 +++ src/nSocket/nstack_rd/nstack_rd_init.c | 202 ++ src/nSocket/nstack_rd/nstack_rd_ip.c | 264 ++ src/nSocket/nstack_rd/nstack_rd_ip.h | 38 + src/nSocket/nstack_rd/nstack_rd_priv.h | 112 + src/nSocket/nstack_rd/nstack_rd_proto.c | 189 ++ src/nSocket/nstack_rd/nstack_rd_proto.h | 35 + 37 files changed, 10683 insertions(+) create mode 100644 src/nSocket/CMakeLists.txt create mode 100644 src/nSocket/include/declare_syscalls.h create mode 100644 src/nSocket/include/nstack_atomic.h create mode 100644 src/nSocket/include/nstack_dmm_api.h create mode 100644 src/nSocket/include/nstack_eventpoll.h create mode 100644 src/nSocket/include/nstack_ip_addr.h create mode 100644 src/nSocket/include/nstack_rd.h create mode 100644 src/nSocket/include/nstack_rd_init.h create mode 100644 src/nSocket/include/nstack_select.h create mode 100644 src/nSocket/include/nstack_sockops.h create mode 100644 src/nSocket/include/nstack_types.h create mode 100644 src/nSocket/include/select_adapt.h create mode 100644 src/nSocket/kernel/linux_kernel_module.c create mode 100644 src/nSocket/kernel/linux_kernel_module.h create mode 100644 src/nSocket/kernel/linux_kernel_socket.c create mode 100644 src/nSocket/kernel/linux_kernel_socket.h create mode 100644 src/nSocket/nstack/event/epoll/nstack_eventpoll.c create mode 100644 src/nSocket/nstack/event/select/nstack_select.c create mode 100644 src/nSocket/nstack/event/select/select_adapt.c create mode 100644 src/nSocket/nstack/nstack.c create mode 100644 src/nSocket/nstack/nstack.h create mode 100644 src/nSocket/nstack/nstack_fd_mng.c create mode 100644 src/nSocket/nstack/nstack_fd_mng.h create mode 100644 src/nSocket/nstack/nstack_info_parse.c create mode 100644 src/nSocket/nstack/nstack_info_parse.h create mode 100644 src/nSocket/nstack/nstack_module.c create mode 100644 src/nSocket/nstack/nstack_module.h create mode 100644 src/nSocket/nstack/nstack_nsocket_construct.c create mode 100644 src/nSocket/nstack/nstack_socket.c create mode 100644 src/nSocket/nstack/nstack_socket.h create mode 100644 src/nSocket/nstack_rd/nstack_rd.c create mode 100644 src/nSocket/nstack_rd/nstack_rd_init.c create mode 100644 src/nSocket/nstack_rd/nstack_rd_ip.c create mode 100644 src/nSocket/nstack_rd/nstack_rd_ip.h create mode 100644 src/nSocket/nstack_rd/nstack_rd_priv.h create mode 100644 src/nSocket/nstack_rd/nstack_rd_proto.c create mode 100644 src/nSocket/nstack_rd/nstack_rd_proto.h (limited to 'src') diff --git a/src/nSocket/CMakeLists.txt b/src/nSocket/CMakeLists.txt new file mode 100644 index 0000000..35b34c6 --- /dev/null +++ b/src/nSocket/CMakeLists.txt @@ -0,0 +1,51 @@ +######################################################################### +# +# 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. +######################################################################### + + +if(WITH_HAL_LIB) +else() + SET(PAL_H_DIRECTORIES "${DMM_DPDK_INSTALL_DIR}/include/dpdk/") + SET(DPDK_LIB_DIRECTORIES "${DMM_DPDK_INSTALL_DIR}/lib64") + SET(DPDK_LIBS "${DPDK_LIB_DIRECTORIES}/librte_eal.so") + list(APPEND DPDK_LIBS "${DPDK_LIB_DIRECTORIES}/librte_mempool.so") + list(APPEND DPDK_LIBS "${DPDK_LIB_DIRECTORIES}/librte_mbuf.so") + list(APPEND DPDK_LIBS "${DPDK_LIB_DIRECTORIES}/librte_ring.so") +endif() + +INCLUDE_DIRECTORIES( + include/ + kernel/ + nstack/ + nstack/event/ + nstack/event/epoll + nstack/event/select + ${SECUREC_SRC_H} + ${PAL_H_DIRECTORIES} + ${CMAKE_CURRENT_LIST_DIR}/../adapt + ${CMAKE_CURRENT_LIST_DIR}/../../thirdparty/json/json-c-0.12.1 +) + +FILE(GLOB_RECURSE nSocket *.c) +ADD_LIBRARY(nStackAPI SHARED ${nSocket}) +TARGET_LINK_LIBRARIES( + nStackAPI + -Wl,--whole-archive + ${LIB_PATH_STATIC}/libjson-c.a + ${LIB_PATH_STATIC}/libglog.a + dmm_api + -Wl,--no-whole-archive,-lstdc++ + ${DPDK_LIBS}) +ADD_DEPENDENCIES(nStackAPI dmm_api) \ No newline at end of file diff --git a/src/nSocket/include/declare_syscalls.h b/src/nSocket/include/declare_syscalls.h new file mode 100644 index 0000000..c4810f5 --- /dev/null +++ b/src/nSocket/include/declare_syscalls.h @@ -0,0 +1,51 @@ +/* +* +* 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. +*/ + +NSTACK_MK_DECL (int, socket, (int, int, int)); +NSTACK_MK_DECL (int, bind, (int, const struct sockaddr *, socklen_t)); +NSTACK_MK_DECL (int, listen, (int, int)); +NSTACK_MK_DECL (int, shutdown, (int, int)); +NSTACK_MK_DECL (int, getsockname, (int, struct sockaddr *, socklen_t *)); +NSTACK_MK_DECL (int, getpeername, (int, struct sockaddr *, socklen_t *)); +NSTACK_MK_DECL (int, getsockopt, (int, int, int, void *, socklen_t *)); +NSTACK_MK_DECL (int, setsockopt, (int, int, int, const void *, socklen_t)); +NSTACK_MK_DECL (int, accept, (int, struct sockaddr *, socklen_t *)); +NSTACK_MK_DECL (int, accept4, + (int, struct sockaddr *, socklen_t *, int flags)); +NSTACK_MK_DECL (int, connect, (int, const struct sockaddr *, socklen_t)); +NSTACK_MK_DECL (ssize_t, recv, (int, void *, size_t, int)); +NSTACK_MK_DECL (ssize_t, send, (int, const void *, size_t, int)); +NSTACK_MK_DECL (ssize_t, read, (int, void *, size_t)); +NSTACK_MK_DECL (ssize_t, write, (int, const void *, size_t)); +NSTACK_MK_DECL (ssize_t, writev, (int, const struct iovec *, int)); +NSTACK_MK_DECL (ssize_t, readv, (int, const struct iovec *, int)); +NSTACK_MK_DECL (ssize_t, sendto, + (int, const void *, size_t, int, const struct sockaddr *, + socklen_t)); +NSTACK_MK_DECL (ssize_t, recvfrom, + (int, void *, size_t, int, struct sockaddr *, socklen_t *)); +NSTACK_MK_DECL (ssize_t, sendmsg, (int, const struct msghdr *, int flags)); +NSTACK_MK_DECL (ssize_t, recvmsg, (int, struct msghdr *, int flags)); +NSTACK_MK_DECL (int, close, (int)); +NSTACK_MK_DECL (int, select, + (int, fd_set *, fd_set *, fd_set *, struct timeval *)); +NSTACK_MK_DECL (int, ioctl, (int, unsigned long, unsigned long)); +NSTACK_MK_DECL (int, fcntl, (int, int, unsigned long)); +NSTACK_MK_DECL (int, epoll_create, (int)); +NSTACK_MK_DECL (int, epoll_ctl, (int, int, int, struct epoll_event *)); +NSTACK_MK_DECL (int, epoll_wait, (int, struct epoll_event *, int, int)); +NSTACK_MK_DECL (pid_t, fork, (void)); +#undef NSTACK_MK_DECL diff --git a/src/nSocket/include/nstack_atomic.h b/src/nSocket/include/nstack_atomic.h new file mode 100644 index 0000000..37ab451 --- /dev/null +++ b/src/nSocket/include/nstack_atomic.h @@ -0,0 +1,57 @@ +/* +* +* 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 _NSTACK_ATOMIC_H_ +#define _NSTACK_ATOMIC_H_ +#include +#include + +#include "nstack_types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif + +typedef struct +{ + volatile ns_int32 counter; +} atomic_t; + +#define atomic_set(v, i) ((v)->counter = (i)) + +#define atomic_fetch_and_add(v, i) __sync_fetch_and_add(&(v)->counter, i) +#define atomic_add_and_fetch(v, i) __sync_add_and_fetch(&(v)->counter, i) + +#define atomic_fetch_and_sub(v, i) __sync_fetch_and_sub(&(v)->counter, i) +#define atomic_sub_and_fetch(v, i) __sync_sub_and_fetch(&(v)->counter, i) + +#define atomic_read(v) atomic_fetch_and_add(v, 0) +#define atomic_inc(v) atomic_add_and_fetch(v, 1) +#define atomic_dec(v)atomic_sub_and_fetch(v, 1) +#define atomic_add(v, i) atomic_add_and_fetch(v, i) +#define atomic_sub(v, i) atomic_sub_and_fetch(v,i) + +#define cas(ptr, oldValue, exchage) __sync_bool_compare_and_swap(ptr, oldValue, exchage) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/nSocket/include/nstack_dmm_api.h b/src/nSocket/include/nstack_dmm_api.h new file mode 100644 index 0000000..4caeb5e --- /dev/null +++ b/src/nSocket/include/nstack_dmm_api.h @@ -0,0 +1,92 @@ +/* +* +* 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 __NSOCKET_DMM_API_H__ +#define __NSOCKET_DMM_API_H__ + +#include +#include +#include +#include +#include +#include +#include +#include "nstack_rd_data.h" + +/* + *Standard api interface definition. + *these interface is provided by Protocol stack to nStack + */ +typedef struct __nstack_socket_ops +{ +#undef NSTACK_MK_DECL +#define NSTACK_MK_DECL(ret, fn, args) ret (*pf##fn) args +#include "declare_syscalls.h" +} nstack_socket_ops; + +typedef enum +{ + STACK_FD_INVALID_CHECK, /*check wether fd is created by this stack */ + STACK_FD_FUNCALL_CHECK, /*check this stack surpport default call */ +} nstack_fd_check; + +typedef enum +{ + nstack_ep_triggle_add, + nstack_ep_triggle_mod, + nstack_ep_triggle_del +} nstack_ep_triggle_ops_t; + +/* + *Interactive interface for Protocol stack and nStack defined here + *these interface is provided by Protocol stack to nStack + */ +typedef struct __nstack_extern_ops +{ + int (*module_init) (void); /*stack module init */ + int (*fork_init_child) (pid_t p, pid_t c); /*after fork, stack child process init again if needed. */ + void (*fork_parent_fd) (int s, pid_t p); /*after fork, stack parent process proc again if needed. */ + void (*fork_child_fd) (int s, pid_t p, pid_t c); /*after fork, child record pid for recycle if needed. */ + void (*fork_free_fd) (int s, pid_t p, pid_t c); /*for SOCK_CLOEXEC when fork if needed. */ + unsigned int (*ep_ctl) (int epFD, int proFD, int ctl_ops, struct epoll_event * event, void *pdata); /*when fd add to epoll fd, triggle stack to proc if need */ + unsigned int (*ep_getevt) (int epFD, int profd, unsigned int events); /*check whether some events exist really */ + int (*ep_prewait_proc) (int epfd); + int (*stack_fd_check) (int s, int flag); /*check whether fd belong to stack, if belong, return 1, else return 0 */ + int (*stack_alloc_fd) (); /*alloc a fd id for epoll */ + int (*peak) (int s); /*used for stack-x , isource maybe no need */ +} nstack_extern_ops; + +/* + *The event notify interface provided to the protocol stack by nStack + *these interface is provided by nStack to Protocol stack + */ +typedef struct __nstack_event_cb +{ + void *handle; /*current so file handler */ + int type; /*nstack is assigned to the protocol stack and needs to be passed to nstack when the event is reported */ + int (*event_cb) (void *pdata, int events); +} nstack_event_cb; + +typedef struct __nstack_proc_cb +{ + nstack_socket_ops socket_ops; /*posix socket api */ + nstack_extern_ops extern_ops; /*other proc callback */ +} nstack_proc_cb; + +typedef int (*nstack_stack_registe_fn) (nstack_proc_cb * proc_fun, + nstack_event_cb * event_ops); + +#endif diff --git a/src/nSocket/include/nstack_eventpoll.h b/src/nSocket/include/nstack_eventpoll.h new file mode 100644 index 0000000..1abc055 --- /dev/null +++ b/src/nSocket/include/nstack_eventpoll.h @@ -0,0 +1,338 @@ +/* +* +* 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 _NSTACK_EVENTPOOL_H +#define _NSTACK_EVENTPOOL_H + +#include "ephlist.h" +#include "eprb_tree.h" +#include "common_mem_api.h" +#include "types.h" +#include +#include +#include +#include +#include "nstack_securec.h" +#include "nstack_log.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSTACK_MAX_EPOLL_INFO_NUM 8192 +#define NSTACK_MAX_EPOLL_NUM NSTACK_MAX_EPOLL_INFO_NUM +#define NSTACK_MAX_EPITEM_NUM (NSTACK_MAX_EPOLL_NUM*2) + +#define MP_NSTACK_EPOLL_INFO_NAME "nsep_info" +#define MP_NSTACK_EVENTPOLL_POOL "nsep_eventpoll" /* Pool of struct eventpoll */ +#define MP_NSTACK_EPITEM_POOL "nsep_epitem" /* Pool of struct epitem */ + +#define MP_NSTACK_EPINFO_RING_NAME "nsep_info_ring" +#define MP_NSTACK_EPITEM_RING_NAME "nsep_item_ring" +#define MP_NSTACK_EVENTPOOL_RING_NAME "nsep_event_ring" + +#define NSTACK_FORK_NUM 32 +#define NSTACK_EPOL_FD 1 + +#define NSEP_SMOD_MAX 8 + +#define NSEP_EP_UNACTIVE_PTR ((void *) -1L) + +COMPAT_PROTECT (NSEP_SMOD_MAX, 8); + +typedef struct +{ + u32 pid_used_size; + u32 pid_array[NSTACK_FORK_NUM]; +} nsep_pidinfo; + +struct eventpoll +{ + + /* + * Protect the this structure access + * This is for event add to ready list and poll out + */ + sys_sem_st lock; + + /* + * This semaphore is used to ensure that files are not removed + * while epoll is using them. This is read-held during the event + * processing loop and it is write-held during the file cleanup + * path, the epoll file exit code and the ctl operations. + * When we do epoll_ctl, we write lock + * When we collecting data , we read lock + */ + sys_sem_st sem; + + /* + * This sempaphore is used to block epoll_wait function + */ + sem_t waitSem; + + /* List of ready file descriptors */ + struct ep_hlist rdlist; + + /* When poll data out, we need this list to store tmp epitems */ + struct epitem *ovflist; + + /* RB-Tree root used to store mastered fd structs */ + struct ep_rb_root rbr; + + /* This specifies the file descriptor value of epoll instance, currenlty it is just used for debugging */ + int epfd; + u32 pid; + nsfw_res res_chk; +}; + +struct eventpoll_pool +{ + void *ring; + struct eventpoll *pool; +}; + +typedef struct +{ + int iindex; + int iNext; + int fd; + i32 epaddflag; + i32 fdtype; /*0: socket fd, 1: epoll fd */ + i32 rlfd; /* copy of fdInf->rlfd */ + i32 rmidx; /* copy of fdInf->rmidx */ + i32 protoFD[NSEP_SMOD_MAX]; /* copy of fdInf->protoFD */// Here we need to set router infomations dependency + struct eventpoll *ep; + sys_sem_st epiLock; + sys_sem_st freeLock; + struct ep_list epiList; /* This restore the epitem of this file descriptor */ + u32 sleepTime; //add for NSTACK_SEM_SLEEP + nsep_pidinfo pidinfo; + nsfw_res res_chk; + void *private_data; /*add for degbu, just used to record extern infomation, for example sbr conn */ + i32 reserv[4]; +} nsep_epollInfo_t; + +typedef struct +{ + void *ring; + nsep_epollInfo_t *pool; + char last_reserve[8]; //reserve for update +} nsep_infoPool_t; + +struct epitem +{ + struct ep_rb_node rbn; + struct ep_hlist_node rdllink; + struct ep_hlist_node lkFDllink; + int nwait; + struct eventpoll *ep; + nsep_epollInfo_t *epInfo; + struct epitem *next; + struct epoll_event event; + struct list_node fllink; + unsigned int revents; + unsigned int ovf_revents; + int fd; + u32 pid; + void *private_data; + nsfw_res res_chk; +}; + +struct epitem_pool +{ + void *ring; + struct epitem *pool; +}; + +typedef struct +{ + struct eventpoll_pool epollPool; + struct epitem_pool epitemPool; + nsep_infoPool_t infoPool; + nsep_epollInfo_t **infoSockMap; // The map of epInfo and socket + +} nsep_epollManager_t; +extern nsep_epollManager_t g_epollMng; +#define nsep_getManager() (&g_epollMng) + +extern int nsep_alloc_eventpoll (struct eventpoll **data); +extern int nsep_free_eventpoll (struct eventpoll *ep); +extern int nsep_alloc_epitem (struct epitem **data); +extern int nsep_free_epitem (struct epitem *data); +extern int nsep_alloc_epinfo (nsep_epollInfo_t ** data); +extern int nsep_free_epinfo (nsep_epollInfo_t * info); + +extern int nsep_epitem_remove (nsep_epollInfo_t * pinfo, u32 pid); + +extern struct epitem *nsep_find_ep (struct eventpoll *ep, int fd); +extern int nsep_epctl_add (struct eventpoll *ep, int fd, + struct epoll_event *events); +extern int nsep_epctl_del (struct eventpoll *ep, struct epitem *epi); +extern int nsep_epctl_mod (struct eventpoll *ep, + nsep_epollInfo_t * epInfo, + struct epitem *epi, struct epoll_event *events); +extern int nsep_ep_poll (struct eventpoll *ep, struct epoll_event *events, + int maxevents, int *eventflag, int num); +extern void nsep_remove_epfd (nsep_epollInfo_t * info); +extern void nsep_close_epfd (struct eventpoll *ep); + +/** + * @Function nsep_init_infoSockMap + * @Description initial map of epoll info and socket + * @param none + * @return 0 on success, -1 on error + */ +extern int nsep_init_infoSockMap (); +extern void nsep_set_infoSockMap (int sock, nsep_epollInfo_t * info); +extern nsep_epollInfo_t *nsep_get_infoBySock (int sock); +extern int nsep_alloc_infoWithSock (int nfd); +extern void nsep_set_infoProtoFD (int fd, int modInx, int protoFD); +extern int nsep_get_infoProtoFD (int fd, int modInx); +extern void nsep_set_infomdix (int fd, int rmidx); +extern int nsep_get_infoMidx (int fd); +extern void nsep_set_infoRlfd (int fd, int rlfd); +extern int nsep_get_infoRlfd (int fd); +extern void nsep_set_infoSleepTime (int fd, u32 sleepTime); +extern int nsep_get_infoSleepTime (int fd); +extern void nsep_set_infoEp (int fd, struct eventpoll *ep); +extern struct eventpoll *nsep_get_infoEp (int fd); +extern int nsep_free_infoWithSock (int sock); +extern int nstack_ep_unlink (struct eventpoll *ep, struct epitem *epi); + +/* Attach shared memory */ +extern int nsep_create_memory (); +extern int nsep_attach_memory (); +extern int nsep_ep_fdinfo_release (int sock); +extern int nsep_epoll_close (int sock); +extern void nsep_fork_child_proc (u32_t ppid); +extern void nsep_fork_parent_proc (u32_t ppid, u32_t cpid); + +static inline i32 +nsep_for_pidinfo_init (nsep_pidinfo * pidinfo) +{ + int ret; + ret = MEMSET_S (pidinfo, sizeof (*pidinfo), 0, sizeof (*pidinfo)); + if (EOK != ret) + { + NSSOC_LOGERR ("MEMSET_S failed]ret=%d", ret); + return -1; + } + return 0; +} + +static inline int +nsep_add_pid (nsep_pidinfo * pidinfo, pid_t pid) +{ + int i; + + for (i = 0; i < NSTACK_FORK_NUM; i++) + { + if ((0 == pidinfo->pid_array[i]) + && (__sync_bool_compare_and_swap (&pidinfo->pid_array[i], 0, pid))) + { + if (pidinfo->pid_used_size < i + 1) + { + pidinfo->pid_used_size = i + 1; + } + return 0; + } + } + return -1; +} + +static inline int +nsep_del_pid (nsep_pidinfo * pidinfo, pid_t pid) +{ + int i; + + for (i = 0; i < pidinfo->pid_used_size && i < NSTACK_FORK_NUM; i++) + { + if (pid == pidinfo->pid_array[i]) + { + pidinfo->pid_array[i] = 0; + return 0; + } + } + return -1; +} + +static inline int +nsep_del_last_pid (nsep_pidinfo * pidinfo, pid_t pid) +{ + int i; + int count = 0; + int deleted = 0; + for (i = 0; i < pidinfo->pid_used_size && i < NSTACK_FORK_NUM; i++) + { + if (pid == pidinfo->pid_array[i]) + { + pidinfo->pid_array[i] = 0; + deleted = 1; + continue; + } + + if (pidinfo->pid_array[i] != 0) + { + ++count; + } + } + + if (!deleted) + { + return -1; + } + + return count; +} + +static inline int +nsep_is_pid_exist (nsep_pidinfo * epinf, pid_t pid) +{ + int i; + + for (i = 0; i < epinf->pid_used_size && i < NSTACK_FORK_NUM; i++) + { + if (pid == epinf->pid_array[i]) + { + return 1; + } + } + return 0; +} + +static inline int +nsep_is_pid_array_empty (nsep_pidinfo * epinf) +{ + int i; + for (i = 0; i < epinf->pid_used_size && i < NSTACK_FORK_NUM; i++) + { + if (epinf->pid_array[i] != 0) + { + return 0; + } + } + return 1; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSTACK_EVENTPOLL_H */ diff --git a/src/nSocket/include/nstack_ip_addr.h b/src/nSocket/include/nstack_ip_addr.h new file mode 100644 index 0000000..8b15854 --- /dev/null +++ b/src/nSocket/include/nstack_ip_addr.h @@ -0,0 +1,36 @@ +/* +* +* 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 __NSTACK_IP_ADDR_H__ +#define __NSTACK_IP_ADDR_H__ + +#ifndef ip4_addr1_16 +#include "nstack_types.h" + +/* Get one byte from the 4-byte address */ +#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0]) /* ip4_addr1(ipaddr) */ +#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1]) /* ip4_addr2(ipaddr) */ +#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2]) /* ip4_addr3(ipaddr) */ +#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3]) /* ip4_addr4(ipaddr) */ + +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) /*ip4_addr1_16(ipaddr) */ +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) /*ip4_addr2_16(ipaddr) */ +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) /*ip4_addr3_16(ipaddr) */ +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) /*ip4_addr4_16(ipaddr) */ +#endif +#endif diff --git a/src/nSocket/include/nstack_rd.h b/src/nSocket/include/nstack_rd.h new file mode 100644 index 0000000..a93f6a6 --- /dev/null +++ b/src/nSocket/include/nstack_rd.h @@ -0,0 +1,47 @@ +/* +* +* 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 __NSTACK_RD_H +#define __NSTACK_RD_H + +/*look up chose info by key*/ +typedef struct __nstack_rd_key +{ + int type; + union + { + unsigned int ip_addr; + unsigned int proto_type; + }; +} nstack_rd_key; + +#define NSTACK_RD_MAX (1 * 1024 * 1024) + +/* + *rd synchronism + * + */ +int nstack_rd_sys (); +int nstack_rd_age (); + +/* + *get stackid by some info + *if input is ip, the value must be net order + * + */ +int nstack_rd_get_stackid (nstack_rd_key * addr, int *stackid); + +#endif diff --git a/src/nSocket/include/nstack_rd_init.h b/src/nSocket/include/nstack_rd_init.h new file mode 100644 index 0000000..cf5073e --- /dev/null +++ b/src/nSocket/include/nstack_rd_init.h @@ -0,0 +1,45 @@ +/* +* +* 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 _NSTACK_RD_INIT_H_ +#define _NSTACK_RD_INIT_H_ +#include "nstack_rd_data.h" + +#define NSTACK_RD_CHECK_BELONG (1) +#define NSTACK_RD_CHECK_NOT_BELONG (0) + +typedef struct __nstack_stack_info +{ + /*stack name */ + char name[STACK_NAME_MAX]; + /*stack id */ + int stack_id; + /*when route info not found, high priority stack was chose, same priority chose fist input one */ + int priority; /*0: highest: route info not found choose first */ +} nstack_stack_info; + +/*get rd info. if return ok, data callee alloc memory, caller free, else caller don't free*/ +typedef int (*nstack_get_route_data) (rd_route_data ** data, int *num); + +/* + *rd init + *defualtid: if all module check fail, just return defualt id + *return : 0 success, -1 fail + */ +int nstack_rd_init (nstack_stack_info * pstack, int num, + nstack_get_route_data * pfun, int fun_num); + +#endif diff --git a/src/nSocket/include/nstack_select.h b/src/nSocket/include/nstack_select.h new file mode 100644 index 0000000..bb23105 --- /dev/null +++ b/src/nSocket/include/nstack_select.h @@ -0,0 +1,153 @@ +/* +* +* 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 * + *----------------------------------------------*/ + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ + +/*==============================================* + * project-wide global variables * + *----------------------------------------------*/ + +/*==============================================* + * routines' or functions' implementations * + *----------------------------------------------*/ + +#define NSTACK_SELECT_MODULE + +#ifdef NSTACK_SELECT_MODULE + +#ifndef __NSTACK_SELECT_H__ +#define __NSTACK_SELECT_H__ + +#include +#include +#include +#include +#include "select_adapt.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef int (*get_select_event) (int nfds, fd_set * readfd, + fd_set * writefd, fd_set * exceptfd, + struct timeval * timeout); +typedef struct +{ + unsigned char fds_bits[(NSTACK_SETSIZE + 7) >> 3]; +} __attribute__ ((packed)) nstack_fd_set; + +#define NSTACK_FD_SET(n, p) ((p)->fds_bits[(n)>>3]|=1U<<((n)&0x07)) +#define NSTACK_FD_ISSET(n,p) (((p)->fds_bits[(n)>>3]&(1U<<((n)&0x07)))?1:0) +#define NSTACK_FD_CLR(n,p) ((p)->fds_bits[(n)>>3]&=~(1U<<((n)&0x07))) +#define NSTACK_FD_ZERO(p) (MEMSET_S((void *)(p), sizeof(*(p)),0,sizeof(*(p)))) +#define NSTACK_FD_OR(p1 ,p2) {\ + int i;\ + for(i = 0; i < (NSTACK_SETSIZE+7)>>3; i++){\ + (p1)->fds_bits[i] |= (p2)->fds_bits[i];\ + }\ +} + +struct select_cb_p +{ + union + { + nstack_fd_set nstack_readset; + fd_set readset; + }; + union + { + nstack_fd_set nstack_writeset; + fd_set writeset; + }; + union + { + nstack_fd_set nstack_exceptset; + fd_set exceptset; + }; + + union + { + i32 count; + i32 readyset; + }; + + i32 inx; + i32 select_errno; +}; + +struct select_entry_info +{ + i32 set_num; //how many select_c_p is set + i32 index; //the frist cb was set +}; + +struct select_entry +{ + struct select_cb_p cb[NSTACK_MAX_MODULE_NUM]; + struct select_cb_p ready; + struct select_entry *next; + struct select_entry *prev; + struct select_entry_info info; + select_sem_t sem; +}; + +struct select_module_info +{ + + struct select_entry *entry_head; + struct select_entry *entry_tail; + get_select_event get_select_fun_nonblock[NSTACK_MAX_MODULE_NUM]; + get_select_event get_select_fun_block[NSTACK_MAX_MODULE_NUM]; + get_select_event default_fun; + i32 default_mod; + volatile i32 inited; + select_spinlock_t lock; + select_sem_t sem; +}; + +extern i32 select_cb_split_by_mod (i32 nfds, + fd_set * readfd, + fd_set * writefd, + fd_set * exceptfd, + struct select_entry *entry); +extern void entry_module_fdset (struct select_entry *entry, + i32 fd_size, + nstack_fd_set * readfd, + nstack_fd_set * writefd, + nstack_fd_set * exceptfd, i32 inx); +extern i32 select_scan (struct select_entry *entry); +extern i32 select_add_cb (struct select_entry *entry); +extern i32 select_rm_cb (struct select_entry *entry); +extern i32 select_entry_reset (struct select_entry *entry); +extern i32 select_module_init (); +extern struct select_module_info *get_select_module (void); +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __NSTACK_SELECT_H__ */ + +#endif /* NSTACK_SELECT_MODULE */ diff --git a/src/nSocket/include/nstack_sockops.h b/src/nSocket/include/nstack_sockops.h new file mode 100644 index 0000000..cc430d5 --- /dev/null +++ b/src/nSocket/include/nstack_sockops.h @@ -0,0 +1,55 @@ +/* +* +* 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 _NSTACK_SOCKOPS_H_ +#define _NSTACK_SOCKOPS_H_ + +#include "nstack_log.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif + +#define NSTACK_CAL_FUN(ops, fun, args, retval) \ +{\ + if(NULL != (ops) && NULL != (ops)->pf##fun)\ + {\ + if((retval = ((ops)->pf##fun args)) == -1)\ + {\ + NSSOC_LOGDBG("function=%s excute failed,ret=%d.errno=%d.", #fun, retval, errno); \ + }\ + }\ + else\ + {\ + NSSOC_LOGERR("NULL address erro, ops_pointer=%p,function=%s", (ops), #fun); \ + errno = EBADF; \ + }\ +} + +#define NSTACK_SET_OPS_FUN(ops, fun, destFunc) \ + if(NULL != (ops)){ \ + (ops)->pf##fun = (destFunc);\ + } + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/nSocket/include/nstack_types.h b/src/nSocket/include/nstack_types.h new file mode 100644 index 0000000..90b538e --- /dev/null +++ b/src/nSocket/include/nstack_types.h @@ -0,0 +1,152 @@ +/* +* +* 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 _NSTACK_TYPES_H_ +#define _NSTACK_TYPES_H_ +#include +#include +#include +#include +#include + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif + +#ifndef NSTACK_MAX_U32_NUM +#define NSTACK_MAX_U32_NUM ((u32_t)0xffffffff) +#endif + +#ifndef NSTACK_MAX_S32_NUM +#define NSTACK_MAX_S32_NUM ((s32_t)0x7fffffff) +#endif + +#ifndef NSTACK_MAX_U64_NUM +#define NSTACK_MAX_U64_NUM ((u64_t)0xffffffffffffffff) +#endif + +#ifndef NSTACK_MAX_S64_NUM +#define NSTACK_MAX_S64_NUM ((s64_t)0x7fffffffffffffff) +#endif + +typedef uint64_t u64_t; +typedef int64_t s64_t; + +typedef uint32_t u32_t; +typedef int32_t s32_t; + +typedef uint16_t u16_t; +typedef int16_t s16_t; + +typedef uint8_t u8_t; +typedef int8_t s8_t; + +typedef uintptr_t mem_ptr_t; + +typedef s8_t err_t; + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ + +#ifndef ns_bool +typedef unsigned char ns_bool; +#endif + +#ifndef ns_false +#define ns_false 0 +#endif + +#ifndef ns_true +#define ns_true 1 +#endif + +#ifndef ns_success +#define ns_success 0 +#endif + +#ifndef ns_fail +#define ns_fail -1 +#endif + +#ifndef ns_static +#define ns_static static +#endif + +#ifndef ns_uint32 +typedef unsigned int ns_uint32; +#endif + +#ifndef ns_int32 +typedef signed int ns_int32; +#endif + +#ifndef ns_char +typedef char ns_char; +#endif + +#ifndef ns_uchar +typedef unsigned char ns_uchar; +#endif + +#ifndef ns_int8 +typedef signed char ns_int8; +#endif + +#ifndef ns_uint8 +typedef unsigned char ns_uint8; +#endif + +#ifndef ns_uint16 +typedef unsigned short ns_uint16; +#endif + +#ifndef ns_int16 +typedef signed short ns_int16; +#endif + +#ifndef ns_uint +typedef unsigned int ns_uint; +#endif + +#ifndef ns_int +typedef signed int ns_int; +#endif + +#ifndef ns_ullong +typedef unsigned long long ns_ullong; +#endif + +#ifndef ns_llong +typedef long long ns_llong; +#endif + +#ifdef ns_slong +typedef signed long ns_slong; +#endif + +#ifdef ns_ulong +typedef unsigned long ns_ulong; +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* _NSTACK_TYPES_H_ */ diff --git a/src/nSocket/include/select_adapt.h b/src/nSocket/include/select_adapt.h new file mode 100644 index 0000000..2898c76 --- /dev/null +++ b/src/nSocket/include/select_adapt.h @@ -0,0 +1,105 @@ +/* +* +* 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 * + *----------------------------------------------*/ + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ + +/*==============================================* + * project-wide global variables * + *----------------------------------------------*/ + +/*==============================================* + * routines' or functions' implementations * + *----------------------------------------------*/ + +#ifndef __SELECT_ADAPT_H__ +#define __SELECT_ADAPT_H__ + +#include "types.h" +#include "nstack_module.h" +#include "common_mem_spinlock.h" +#include "nstack_securec.h" +#include "common_func.h" + +#define SBR_MAX_FD_NUM MAX_SOCKET_NUM + +#define NSTACK_SELECT_MAX_FD 8192 +#define NSTACK_SETSIZE 8192 + +#define FREE_FD_SET(readfd, writefd, exceptfd) {\ + if(readfd)\ + free(readfd);\ + if(writefd)\ + free(writefd);\ + if(exceptfd)\ + free(exceptfd);\ +} + +typedef sem_t select_sem_t; +typedef common_mem_spinlock_t select_spinlock_t; + +#define select_spin_lock(lock) (common_mem_spinlock_lock((lock))) +#define select_spin_unlock(lock) (common_mem_spinlock_unlock((lock))) +#define select_spin_lock_init(lock) (common_mem_spinlock_init((lock))) + +#define select_sem_wait(sem) (sem_wait((sem))) +#define select_sem_init(sem, share, val) (sem_init((sem), (share), (val))) +#define select_sem_post(sem) (sem_post((sem))) + +/*************input form other modules***************************/ +extern nstack_module_info g_nstack_modules; +#define get_mode_num() (g_nstack_modules.modNum) +#define get_mode_linux_index() (g_nstack_modules.fix_mid) + +struct select_comm_fd_map +{ + i32 mod_fd[NSTACK_MAX_MODULE_NUM]; //save modules fd + i32 index; //-1 mean not select modules +}; + +struct select_mod_fd_map +{ + i32 *comm_fd; //the fd app used +}; + +struct select_fd_map_inf +{ + + struct select_comm_fd_map *fdinf; //NSTACK_MAX_SOCK_NUM + struct select_mod_fd_map modinf[NSTACK_MAX_MODULE_NUM]; + +}; +void *select_alloc (int size); +void select_free (char *p); +void reset_select_fdinf (i32 fd); +i32 select_get_modfd (i32 fd, i32 inx); +i32 select_set_modfd (i32 fd, i32 inx, i32 modfd); +i32 select_get_modindex (i32 fd); +i32 select_get_commfd (i32 modfd, i32 inx); +i32 select_set_commfd (i32 modfd, i32 inx, i32 fd); +i32 fdmapping_init (void); +i32 select_set_index (i32 fd, i32 inx); +i32 select_set_profd (i32 fd, i32 profd); +void nssct_close (i32 cfd, i32 inx); +void nssct_create (i32 cfd, i32 mfd, i32 inx); +void nssct_set_index (i32 fd, i32 inx); + +#endif diff --git a/src/nSocket/kernel/linux_kernel_module.c b/src/nSocket/kernel/linux_kernel_module.c new file mode 100644 index 0000000..f6feb71 --- /dev/null +++ b/src/nSocket/kernel/linux_kernel_module.c @@ -0,0 +1,337 @@ +/* +* +* 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. +*/ + +#pragma GCC diagnostic ignored "-Wcpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nstack_types.h" +#include "nstack_sockops.h" +#include "nstack_log.h" +#include "linux_kernel_module.h" +#include "linux_kernel_socket.h" +#include "nsfw_base_linux_api.h" +#include "nstack_fd_mng.h" +#include "nstack_dmm_api.h" + +#define SK_MAX_EP_EVENT 1024 + +kernel_stack_info_t g_ksInfo = {.thread_inited = ks_false,.epfd = + -1,.checkEpollFD = -1 +}; + +/*design ensures that g_ksInfo is not write accessed at the same time. +only read is done simultaneously with no chance of other thread writing it. +so no protection needed.*/ +/* Custodial pointer not freed for events at end of this function */ +/* This can be ignored as this is a thread and reuns in infinite loop. Hence will never return */ +void * +ks_ep_thread (void *arg) +{ + int eventNum = 0; + int loop = 0; + struct epoll_event *events = + (struct epoll_event *) malloc (SK_MAX_EP_EVENT * + sizeof (struct epoll_event)); + struct epoll_event *innerEvt = + (struct epoll_event *) malloc (SK_MAX_EP_EVENT * + sizeof (struct epoll_event)); + + if (NULL == events || NULL == innerEvt) + { + NSSOC_LOGERR ("malloc events failed"); + + if (events) + { + free (events); + events = NULL; /* Set NULL to pointer after free */ + } + + if (innerEvt) + { + free (innerEvt); + innerEvt = NULL; /* Set NULL to pointer after free */ + } + /* When ks_ep_thread failed, it should set g_ksInfo.thread_inited ks_true, otherwise,it will result kernel_stack_register in dead loop */ + g_ksInfo.thread_inited = ks_true; + return NULL; + } + + if (-1 == g_ksInfo.epfd) + { + NSTACK_CAL_FUN (&g_ksInfo.libcOps, epoll_create, (1), g_ksInfo.epfd); + } + + if (-1 == g_ksInfo.epfd) + { + g_ksInfo.thread_inited = ks_true; + + if (events) + { + free (events); + events = NULL; /* Set NULL to pointer after free */ + } + + if (innerEvt) + { + free (innerEvt); + innerEvt = NULL; /* Set NULL to pointer after free */ + } + + return NULL; + } + + g_ksInfo.thread_inited = ks_true; + + do + { + + NSTACK_CAL_FUN (&g_ksInfo.libcOps, epoll_wait, + (g_ksInfo.epfd, events, SK_MAX_EP_EVENT, -1), eventNum); + + if (0 == eventNum) + { + sys_sleep_ns (0, 100000); + + } + + for (loop = 0; loop < eventNum; loop++) + { + + NSSOC_LOGDBG ("Epoll]events=%u,epfd=%d", events[loop].events, + events[loop].data.fd); + + if (events[loop].events & EPOLLIN) + { + int i = 0, num = 0, ret = 0, epfd = events[loop].data.fd; + NSTACK_CAL_FUN (&g_ksInfo.libcOps, epoll_wait, + (epfd, innerEvt, SK_MAX_EP_EVENT, 0), num); + + if (0 == num) + { + NSSOC_LOGWAR ("Num is zero"); + continue; + } + + NSTACK_CAL_FUN (&g_ksInfo.libcOps, epoll_ctl, + (g_ksInfo.epfd, EPOLL_CTL_DEL, epfd, NULL), + ret); + + ret = -1; + for (i = 0; i < num; i++) + { + ret &= + g_ksInfo.regVal.event_cb (innerEvt[i].data.ptr, + innerEvt[i].events); + NSSOC_LOGDBG ("Kernel got one event]i=%d,ptr=%d,events=%u", + i, innerEvt[i].data.ptr, innerEvt[i].events); + } + + if (ret) + { + struct epoll_event ev; + ev.data.fd = epfd; + ev.events = EPOLLIN; + NSTACK_CAL_FUN (&g_ksInfo.libcOps, epoll_ctl, + (g_ksInfo.epfd, EPOLL_CTL_ADD, epfd, &ev), + ret); + } + } + } +#ifndef FOR_NSTACK_UT + } + while (1); +#else + } + while (0); + return NULL; +#endif +} + +int +kernel_fd_check (int fd, int flag) +{ + struct epoll_event event; + event.data.fd = fd; + event.events = EPOLLIN | EPOLLERR; + if (fd == g_ksInfo.checkEpollFD) + { + return 0; + } + + /*in order to reduce the cost of epoll ctl */ + if (STACK_FD_FUNCALL_CHECK == flag) + { + return 1; + } + + if (-1 == + nsfw_base_epoll_ctl (g_ksInfo.checkEpollFD, EPOLL_CTL_ADD, fd, &event)) + { + return 0; + } + + nsfw_base_epoll_ctl (g_ksInfo.checkEpollFD, EPOLL_CTL_DEL, fd, NULL); + return 1; +} + +int +kernel_prewait_proc (int epfd) +{ + int ret = 0; + struct epoll_event ep_event; + + NSSOC_LOGINF ("epfd=%d was added", epfd); + if (epfd < 0) + { + return -1; + } + ep_event.data.fd = epfd; + ep_event.events = EPOLLIN | EPOLLET; + ret = lk_epollctl (0, EPOLL_CTL_ADD, epfd, &ep_event); + return ret; +} + +unsigned int +kernel_ep_fd_add (int epFD, int proFD, int ctl_ops, + struct epoll_event *events, void *pdata) +{ + struct epoll_event tmpEvt; + int ret = 0; + tmpEvt.data.ptr = pdata; + tmpEvt.events = events->events; + NSSOC_LOGINF ("epfd=%d,fd=%d,ops=%d, events=%u", epFD, proFD, ctl_ops, + events->events); + switch (ctl_ops) + { + case nstack_ep_triggle_add: + ret = nsfw_base_epoll_ctl (epFD, EPOLL_CTL_ADD, proFD, &tmpEvt); + break; + case nstack_ep_triggle_mod: + ret = nsfw_base_epoll_ctl (epFD, EPOLL_CTL_MOD, proFD, &tmpEvt); + break; + case nstack_ep_triggle_del: + ret = nsfw_base_epoll_ctl (epFD, EPOLL_CTL_DEL, proFD, &tmpEvt); + break; + default: + ret = -1; + break; + } + return ret; +} + +int +kernel_socket (int a, int b, int c) +{ + + return nsfw_base_socket (a, b, c); +} + +int +kernel_module_init () +{ + int retval = 0; + + g_ksInfo.thread_inited = ks_false; + retval = pthread_create (&g_ksInfo.ep_thread, NULL, ks_ep_thread, NULL); + if (retval != 0) + { + NSPOL_LOGERR ("kernel ep thread create fail, errno:%d!", errno); + return ks_fail; + } + + /* The earlier thread "ep_thread" created will exit automatically when + return failure from below if any failure */ + retval = pthread_setname_np (g_ksInfo.ep_thread, K_EPOLL_THREAD_NAME); + if (retval != 0) + { + NSMON_LOGERR + ("pthread_setname_np failed for ep_thread]retval=%d, errno:%d", + retval, errno); + /*set thread name failed no need to return */ + } + + NSSOC_LOGDBG ("New thread started"); + + do + { + sys_sleep_ns (0, 0); + } + while (!g_ksInfo.thread_inited); + + if (-1 == g_ksInfo.epfd) + { + NSPOL_LOGERR ("thread epoll create Err!"); + retval |= -1; + } + return retval; +} + +int +kernel_fd_alloc () +{ + return nsfw_base_socket (AF_UNIX, SOCK_DGRAM, 0); +} + +int +kernel_stack_register (nstack_proc_cb * ops, nstack_event_cb * val) +{ + int retval = 0; + /* Input parameter validation */ + if ((NULL == ops) || (NULL == val)) + { + NSPOL_LOGERR ("input param is NULL"); + return ks_fail; + } + +#undef NSTACK_MK_DECL +#define NSTACK_MK_DECL(ret, fn, args) \ + g_ksInfo.libcOps.pf##fn = nsfw_base_##fn; + +#include "declare_syscalls.h" + + g_ksInfo.regVal = *val; + + /*create a efpd to check fd is ok */ + if (g_ksInfo.checkEpollFD == -1) + { + g_ksInfo.checkEpollFD = nsfw_base_epoll_create (1); + } + + NSSOC_LOGDBG ("start to regist stack"); + + ops->socket_ops = g_ksInfo.libcOps; + MEMSET_S (&(ops->extern_ops), sizeof (ops->extern_ops), 0, + sizeof (ops->extern_ops)); + NSTACK_SET_OPS_FUN (&(ops->socket_ops), listen, lk_listen); + NSTACK_SET_OPS_FUN (&(ops->socket_ops), epoll_ctl, lk_epollctl); + NSTACK_SET_OPS_FUN (&(ops->socket_ops), socket, kernel_socket); + ops->extern_ops.stack_fd_check = kernel_fd_check; + ops->extern_ops.ep_ctl = kernel_ep_fd_add; + ops->extern_ops.ep_prewait_proc = kernel_prewait_proc; + ops->extern_ops.module_init = kernel_module_init; + ops->extern_ops.stack_alloc_fd = kernel_fd_alloc; + + /* don't close file descriptor */ + + return retval ? ks_fail : ks_success; +} diff --git a/src/nSocket/kernel/linux_kernel_module.h b/src/nSocket/kernel/linux_kernel_module.h new file mode 100644 index 0000000..01e0330 --- /dev/null +++ b/src/nSocket/kernel/linux_kernel_module.h @@ -0,0 +1,61 @@ +/* +* +* 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 _LINUX_KERNEL_MODULE_H_ +#define _LINUX_KERNEL_MODULE_H_ + +#include "nstack_dmm_api.h" + +#define K_SELECT_THREAD_NAME "kernel_select" +#define K_EPOLL_THREAD_NAME "kernel_epoll" + +#ifndef ks_success +#define ks_success 0 +#endif + +#ifndef ks_fail +#define ks_fail -1 +#endif + +#ifndef ks_bool +typedef char ks_bool; +#endif + +#ifndef ks_false +#define ks_false 0 +#endif + +#ifndef ks_true +#define ks_true 1 +#endif + +int kernel_stack_register (nstack_proc_cb * ops, nstack_event_cb * val); + +typedef struct +{ + nstack_event_cb regVal; + int epfd; + int checkEpollFD; + pthread_t ep_thread; + ks_bool thread_inited; + pthread_t select_thread; //listen select events + nstack_socket_ops libcOps; +} kernel_stack_info_t; + +extern kernel_stack_info_t g_ksInfo; + +extern int linux_kernel_stack_init (void); +#endif diff --git a/src/nSocket/kernel/linux_kernel_socket.c b/src/nSocket/kernel/linux_kernel_socket.c new file mode 100644 index 0000000..b7ac028 --- /dev/null +++ b/src/nSocket/kernel/linux_kernel_socket.c @@ -0,0 +1,64 @@ +/* +* +* 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. +*/ + +#pragma GCC diagnostic ignored "-Wcpp" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "linux_kernel_socket.h" +#include "linux_kernel_module.h" +#include "nstack_sockops.h" +#include "nstack_securec.h" + +int +lk_listen (int sockfd, int backlog) +{ + int ret = -1; + + NSTACK_CAL_FUN (&g_ksInfo.libcOps, listen, (sockfd, backlog), ret); + return ret; +} + +int +lk_epollctl (int epfd, int op, int protoFd, struct epoll_event *event) +{ + int retVal; + struct epoll_event ev; + + /* Input parameter validation */ + if (NULL == event) + { + NSSOC_LOGERR ("input param event is NULL"); + return -1; + } + + retVal = + MEMCPY_S (&ev, sizeof (struct epoll_event), event, + sizeof (struct epoll_event)); + if (EOK != retVal) + { + NSSOC_LOGERR ("MEMCPY_S failed]ret=%d", retVal); + return -1; + } + ev.data.fd = protoFd; + return g_ksInfo.libcOps.pfepoll_ctl (g_ksInfo.epfd, op, protoFd, &ev); +} diff --git a/src/nSocket/kernel/linux_kernel_socket.h b/src/nSocket/kernel/linux_kernel_socket.h new file mode 100644 index 0000000..9c3d692 --- /dev/null +++ b/src/nSocket/kernel/linux_kernel_socket.h @@ -0,0 +1,36 @@ +/* +* +* 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 _LINUX_KERNEL_SOCKET_H_ +#define _LINUX_KERNEL_SOCKET_H_ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif + +extern int lk_listen (int sockfd, int backlog); +extern int lk_epollctl (int epfd, int op, int protoFd, + struct epoll_event *event); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/nSocket/nstack/event/epoll/nstack_eventpoll.c b/src/nSocket/nstack/event/epoll/nstack_eventpoll.c new file mode 100644 index 0000000..989cdd7 --- /dev/null +++ b/src/nSocket/nstack/event/epoll/nstack_eventpoll.c @@ -0,0 +1,1213 @@ +/* +* +* 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 "nstack_eventpoll.h" +#include "nstack_log.h" +#include "nsfw_recycle_api.h" +#include "nstack_securec.h" +#include "nstack_module.h" +#include "nstack_sockops.h" +#include "nsfw_mem_api.h" +#include "nstack_fd_mng.h" +#include "nstack.h" +#include "nstack_dmm_adpt.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSTACK_EP_TRIGGLE(epFD, proFD, modInx, triggle_ops, event, pdata, ret) \ + if (nstack_extern_deal(modInx).ep_ctl != NULL) \ + { \ + ret = nstack_extern_deal(modInx).ep_ctl((epFD), (proFD), (triggle_ops), (event), pdata); \ + } + +#define nstack_ep_getEvt(epFD, profd, modInx, events, ret) \ + if (nstack_extern_deal(modInx).ep_getevt != NULL)\ + { \ + ret |= nstack_extern_deal(modInx).ep_getevt((epFD), (profd), (events)); \ + } + +#define NSEP_IS_SOCK_VALID(_sock) ((_sock) >= 0 && (u32_t)(_sock) < NSTACK_KERNEL_FD_MAX) + +/*add event to rdlist if event have come in*/ +void +nsep_ctl_event_add (struct epitem *epi, struct eventpoll *ep, + int triggle_ops, unsigned int events) +{ + switch (triggle_ops) + { + case nstack_ep_triggle_add: + if (events & epi->event.events) + { + sys_arch_lock_with_pid (&ep->lock); + + if (!EP_HLIST_NODE_LINKED (&epi->rdllink)) + { + ep_hlist_add_tail (&ep->rdlist, &epi->rdllink); + } + + sys_sem_s_signal (&ep->lock); + sem_post (&ep->waitSem); + } + + break; + + case nstack_ep_triggle_mod: + sys_arch_lock_with_pid (&ep->lock); + + if (events & epi->event.events) + { + if (!EP_HLIST_NODE_LINKED (&epi->rdllink)) + { + ep_hlist_add_tail (&ep->rdlist, &epi->rdllink); + sem_post (&ep->waitSem); + } + } + else + { + if (EP_HLIST_NODE_LINKED (&epi->rdllink) + && (epi->event.events & EPOLLET)) + { + ep_hlist_del (&ep->rdlist, &epi->rdllink); + } + } + + sys_sem_s_signal (&ep->lock); + break; + default: + break; + } + + return; +} + +/* + * Triggle epoll events of stack + * ep - eventpoll instance + * fdInf - file descriptor of stack + * triggle_ops - why triggle + */ +NSTACK_STATIC void +nsep_epctl_triggle (struct epitem *epi, nsep_epollInfo_t * info, + int triggle_ops) +{ + int modInx; + int protoFd = -1; + int epfd = 0; + int ret = 0; + struct eventpoll *ep = NULL; + nsep_epollInfo_t *epInfo = NULL; + + ep = ADDR_SHTOL (epi->ep); + epfd = ep->epfd; + epInfo = nsep_get_infoBySock (epfd); + + NSSOC_LOGINF ("info=%p,info->rmidx=%d,triggle_ops=%d", info, info->rmidx, + triggle_ops); + + /* Now need to triggle userspace network stack events after add operation */ + if (info->rmidx >= 0) + { + /* fix overflow type codedex issue */ + if ((info->rmidx >= NSEP_SMOD_MAX) + || (info->rmidx >= NSTACK_MAX_MODULE_NUM)) + { + return; + } + + NSTACK_EP_TRIGGLE (epInfo->protoFD[info->rmidx], info->rlfd, + info->rmidx, triggle_ops, &(epi->event), info, ret); + + if ((ret >= 0) + && ((nstack_ep_triggle_add == triggle_ops) + || (nstack_ep_triggle_mod == triggle_ops))) + { + epi->revents = ret; + nsep_ctl_event_add (epi, ep, triggle_ops, epi->revents); + info->epaddflag |= (1 << info->rmidx); + } + NSSOC_LOGINF ("info=%p,module=%s,protoFd=%d,triggle_ops=%d, ret:%d", + info, nstack_get_module_name_by_idx (info->rmidx), + info->rlfd, triggle_ops, ret); + } + else + { + nstack_each_modInx (modInx) + { + protoFd = info->protoFD[modInx]; + + if (protoFd < 0) + { + continue; + } + NSTACK_EP_TRIGGLE (epInfo->protoFD[modInx], protoFd, modInx, + triggle_ops, &(epi->event), info, ret); + if ((ret >= 0) + && ((nstack_ep_triggle_add == triggle_ops) + || (nstack_ep_triggle_mod == triggle_ops))) + { + epi->revents |= ret; + nsep_ctl_event_add (epi, ep, triggle_ops, epi->revents); + info->epaddflag |= (1 << modInx); + } + NSSOC_LOGINF ("info=%p,module=%s,protoFd=%d,triggle_ops=%d, ret:%d", + info, nstack_get_module_name_by_idx (modInx), protoFd, + triggle_ops, ret); + } + } + return; +} + +NSTACK_STATIC void +nsep_rbtree_insert (struct eventpoll *ep, struct epitem *epi) +{ + struct ep_rb_node **p = &ep->rbr.rb_node, *parent = NULL; + struct epitem *epic; + u32_t loopCnt = 0; + + while (*p) + { + ++loopCnt; + if (loopCnt > NSTACK_MAX_EPITEM_NUM) + { + NSSOC_LOGERR ("Loop out of range!!!!"); + break; + } + + parent = (struct ep_rb_node *) ADDR_SHTOL (*p); + epic = ep_rb_entry (parent, struct epitem, rbn); + if (epi->fd > epic->fd) + { + p = &(parent->rb_right); + } + else + { + p = &(parent->rb_left); + } + } + + ep_rb_link_node (&epi->rbn, parent, p); + ep_rb_insert_color (&epi->rbn, &ep->rbr); +} + +/* + * This function is called by epctl_add , it will create one epitem of fd, and insert to eventpoll + */ +NSTACK_STATIC int +nsep_insert_node (struct eventpoll *ep, struct epoll_event *event, + nsep_epollInfo_t * fdInfo) +{ + struct epitem *epi; + + if (nsep_alloc_epitem (&epi)) + { + NSSOC_LOGERR ("Can't alloc epitem"); + errno = ENOMEM; + return -1; + } + + EP_HLIST_INIT_NODE (&epi->rdllink); + EP_HLIST_INIT_NODE (&epi->lkFDllink); + + epi->nwait = 0; + epi->ep = (struct eventpoll *) ADDR_LTOSH_EXT (ep); + epi->epInfo = (nsep_epollInfo_t *) ADDR_LTOSH_EXT (fdInfo); + epi->revents = 0; + epi->ovf_revents = 0; + epi->event = *event; + EP_LIST_INIT_NODE (&epi->fllink); + epi->revents = 0; + epi->fd = fdInfo->fd; + + /* Add the current item to the list of active epoll hook for this file + This should lock because file descriptor may be called by other eventpoll */ + + sys_arch_lock_with_pid (&fdInfo->epiLock); + ep_list_add_tail (&fdInfo->epiList, &epi->fllink); + epi->private_data = (void *) ADDR_LTOSH_EXT (fdInfo); + sys_sem_s_signal (&fdInfo->epiLock); + + /* Add epitem to eventpoll fd list, don't need lock here because epoll_ctl will lock before calling this function */ + nsep_rbtree_insert (ep, epi); + + /* Need to poll the events already stored in stack */ + nsep_epctl_triggle (epi, fdInfo, nstack_ep_triggle_add); + + NSSOC_LOGINF ("epfd=%d,ep=%p,fd=%d,epi=%p", ep->epfd, ep, fdInfo->fd, epi); + + return 0; +} + +NSTACK_STATIC int +nsep_isAddValid (int fd) +{ + + if (nstack_fix_fd_check ()) + { + return nstack_fix_fd_check ()(fd, STACK_FD_INVALID_CHECK); + } + return 0; +} + +int +nsep_epctl_add (struct eventpoll *ep, int fd, struct epoll_event *events) +{ + + int ret = 0; + + NSSOC_LOGINF ("epfd=%d,fd=%d,events=%u", ep->epfd, fd, events->events); + + nsep_epollInfo_t *fdInfo = nsep_get_infoBySock (fd); + + if (NULL == fdInfo) + { + if (0 == nsep_isAddValid (fd)) + { + NSSOC_LOGERR ("Invalid add check nfd=%d]", fd); + return -1; + } + if (-1 == nsep_alloc_infoWithSock (fd)) + { + NSSOC_LOGERR ("Can't alloc epInfo for nfd]nfd=%d", fd); + return -1; + } + nsep_set_infoProtoFD (fd, nstack_get_fix_mid (), fd); + fdInfo = nsep_get_infoBySock (fd); + } + + ret = nsep_insert_node (ep, events, fdInfo); + if (0 != ret) + { + NSSOC_LOGWAR ("insert fail]epfd=%d,fd=%d ", ep->epfd, fdInfo->fd); + return -1; + } + + return 0; +} + +int +nsep_epctl_del (struct eventpoll *ep, struct epitem *epi) +{ + int ret = 0; + + nsep_epollInfo_t *epInfo = + (nsep_epollInfo_t *) ADDR_SHTOL (epi->private_data); + NSSOC_LOGINF ("epfd=%d,fd=%d,epi=%p", ep->epfd, epi->fd, epi); // modify log format error + + nsep_epctl_triggle (epi, epInfo, nstack_ep_triggle_del); + + sys_arch_lock_with_pid (&epInfo->epiLock); + ep_list_del (&epInfo->epiList, &epi->fllink); + + sys_sem_s_signal (&epInfo->epiLock); + + sys_arch_lock_with_pid (&ep->lock); + ret = nstack_ep_unlink (ep, epi); + sys_sem_s_signal (&ep->lock); + nsep_free_epitem (epi); + + return ret; +} + +int +nsep_epctl_mod (struct eventpoll *ep, + nsep_epollInfo_t * epInfo, + struct epitem *epi, struct epoll_event *events) +{ + if (NULL == epInfo) + { + errno = EINVAL; + NSSOC_LOGWAR ("epfd=%d, intput epInfo is null err", ep->epfd); + return -1; + } + + NSSOC_LOGINF ("epfd=%d,fd=%d,events=%u", ep->epfd, epInfo->fd, + events->events); + + sys_arch_lock_with_pid (&ep->lock); + epi->event = *events; /* kernel tells me that I need to modify epi->event in lock context */ + sys_sem_s_signal (&ep->lock); + + nsep_epctl_triggle (epi, epInfo, nstack_ep_triggle_mod); + return 0; +} + +/* + * Called by nsep_ep_poll + * proccess the event in the list + */ +static int +nsep_events_proc (struct eventpoll *ep, + struct ep_node_list *nhead, + struct epoll_event *events, int maxevents, int *eventflag, + int num) +{ + struct ep_hlist_node *node = NULL; + struct epitem *epi = NULL; + struct ep_hlist_node *head = nhead->head; + int evt = 0; + + while (head) + { + node = head; + epi = ep_hlist_entry (node, struct epitem, rdllink); + head = (struct ep_hlist_node *) ADDR_SHTOL (node->next); + EP_HLIST_INIT_NODE (node); + + nsep_epollInfo_t *fdInfo = + (nsep_epollInfo_t *) ADDR_SHTOL (epi->private_data); + + if (fdInfo->rmidx != -1) + { + nstack_ep_getEvt (ep->epfd, fdInfo->rlfd, fdInfo->rmidx, + epi->event.events, (epi->revents)); + } + + if (epi->revents) + { + /*set the flag that already have event int the rdlist */ + if (eventflag && (fdInfo->rmidx >= 0) && (fdInfo->rmidx < num)) + { + eventflag[fdInfo->rmidx] = 1; + } + events[evt].events = epi->revents; + events[evt].data = epi->event.data; + NSSOC_LOGDBG ("Add event]epfd=%d,fd=%d,events=%u", ep->epfd, + epi->fd, events[evt].events); + evt++; + } + + if (0 != epi->revents && EPOLLET != (epi->event.events & EPOLLET)) + { + NSSOC_LOGDBG ("Add epi->rdllink,epfd=%d,fd=%d", ep->epfd, epi->fd); + ep_hlist_add_tail (&ep->rdlist, &epi->rdllink); + } + epi->revents = 0; + + if (evt >= maxevents) + break; + } + nhead->head = head; + if (!head) + { + nhead->tail = NULL; + } + return evt; +} + +/* + * Called by epoll_wait + * Wait until events come or timeout + */ +int +nsep_ep_poll (struct eventpoll *ep, struct epoll_event *events, int maxevents, + int *eventflag, int num) +{ + + struct ep_hlist_node *tail = NULL; + struct ep_hlist_node *head = NULL; + struct epitem *epi = NULL; + struct epitem *nepi = NULL; + struct ep_node_list nhead = { 0 }; + int evt = 0; + nsep_epollInfo_t *fdInfo = NULL; + + if (EP_HLIST_EMPTY (&ep->rdlist)) + { + NSSOC_LOGDBG ("ep->rdlist is Empty, epfd=%d", ep->epfd); + return 0; + } + + sys_arch_lock_with_pid (&ep->sem); + + if (EP_HLIST_EMPTY (&ep->rdlist)) + { + goto out; + } + + sys_arch_lock_with_pid (&ep->lock); + head = (struct ep_hlist_node *) ADDR_SHTOL (ep->rdlist.head); + if (!head) + { + sys_sem_s_signal (&ep->lock); + goto out; + } + nhead.head = (struct ep_hlist_node *) ADDR_SHTOL (head->next); + nhead.tail = (struct ep_hlist_node *) ADDR_SHTOL (ep->rdlist.tail); + /*unlink from ep->rdlist */ + EP_HLIST_INIT (&(ep->rdlist)); + ep->ovflist = NULL; + sys_sem_s_signal (&ep->lock); + + /*get event list */ + evt = nsep_events_proc (ep, &nhead, events, maxevents, eventflag, num); + + sys_arch_lock_with_pid (&ep->lock); + /*put rest epitem back to the rdlist */ + if (nhead.head) + { + tail = (struct ep_hlist_node *) ADDR_SHTOL (ep->rdlist.tail); + tail->next = (struct ep_hlist_node *) ADDR_LTOSH (nhead.head); + nhead.head->pprev = (struct ep_hlist_node **) ADDR_LTOSH (&tail->next); + ep->rdlist.tail = (struct ep_hlist_node *) ADDR_LTOSH (nhead.tail); + } + /*put the epitem in ep->ovflist to rdlist */ + for (nepi = (struct epitem *) ADDR_SHTOL (ep->ovflist); + (epi = nepi) != NULL; + nepi = (struct epitem *) ADDR_SHTOL (epi->next), epi->next = + NSEP_EP_UNACTIVE_PTR) + { + epi->revents |= epi->ovf_revents; + /*set the flag that already have event int the rdlist */ + fdInfo = (nsep_epollInfo_t *) ADDR_SHTOL (epi->private_data); + if (eventflag && fdInfo && (fdInfo->rmidx >= 0) + && (fdInfo->rmidx < num)) + { + eventflag[fdInfo->rmidx] = 1; + } + epi->ovf_revents = 0; + if (!EP_HLIST_NODE_LINKED (&epi->rdllink)) + { + ep_hlist_add_tail (&ep->rdlist, &epi->rdllink); + } + } + ep->ovflist = NSEP_EP_UNACTIVE_PTR; + sys_sem_s_signal (&ep->lock); +out: + sys_sem_s_signal (&ep->sem); + NSSOC_LOGDBG ("Return epfd=%d,evt=%d,EP_HLIST_EMPTY(&ep->rdlist)=%d", + ep->epfd, evt, EP_HLIST_EMPTY (&ep->rdlist)); + return evt; +} + +#define FREE_LIST_SIZE 128 +#ifdef FREE_LIST_SIZE +struct free_list +{ + struct free_list *next; + struct list_node *node[FREE_LIST_SIZE]; +}; +#endif + +void +nsep_remove_epfd (nsep_epollInfo_t * pinfo) +{ + pid_t pid = get_sys_pid (); + struct list_node *prenode = NULL; + struct list_node *nextnode = NULL; +#ifdef FREE_LIST_SIZE + struct free_list flist; + struct free_list *fcurr = &flist; +#else + struct list_node **node_arry = NULL; + int lenth = NSTACK_MAX_EPOLL_INFO_NUM * sizeof (struct list_node *); +#endif + struct epitem *epi = NULL; + struct epitem *tepi = NULL; + struct eventpoll *ep = NULL; + u32_t i = 0; + u32_t icnt = 0; + + if (!pinfo) + { + return; + } + /*malloc a block memory to store epitem node, do not use list for maybe free item */ +#ifdef FREE_LIST_SIZE + flist.next = 0; +#else + node_arry = (struct list_node **) malloc (lenth); + if (!node_arry) + { + NSSOC_LOGERR ("remove fd from ep malloc mem fail]fd=%d,ep=%p", + pinfo->fd, pinfo->ep); + return; + } + + int retVal = MEMSET_S (node_arry, lenth, 0, lenth); + if (EOK != retVal) + { + NSSOC_LOGERR ("MEMSET_S failed]retVal=%d", retVal); + free (node_arry); + return; + } +#endif + sys_arch_lock_with_pid (&pinfo->epiLock); + /*list head must be not null */ + prenode = (struct list_node *) ADDR_SHTOL (pinfo->epiList.head); + nextnode = (struct list_node *) ADDR_SHTOL (prenode->next); + icnt = 0; + + /*find all node that pid is belong to itself */ + while (nextnode) + { + if (++i > NSTACK_MAX_EPOLL_INFO_NUM) + { + /*record the exception log */ + NSSOC_LOGERR ("error maybe happen]free pinfo=%p", pinfo); + break; + } + epi = ep_list_entry (nextnode, struct epitem, fllink); + if (pid == epi->pid) + { + prenode->next = nextnode->next; + nextnode->next = NULL; + /*put into release list */ +#ifdef FREE_LIST_SIZE + if ((icnt % FREE_LIST_SIZE) == 0 && icnt) + { + struct free_list *fnext = + (struct free_list *) malloc (sizeof (struct free_list)); + if (!fnext) + { + NSSOC_LOGERR ("Out of memory for freelist]fd=%d icnt=%u", + pinfo->fd, icnt); + break; + } + fnext->next = NULL; + fcurr->next = fnext; + fcurr = fnext; + } + fcurr->node[icnt % FREE_LIST_SIZE] = nextnode; +#else + node_arry[icnt] = nextnode; +#endif + icnt++; + } + else + { + prenode = nextnode; + } + nextnode = (struct list_node *) ADDR_SHTOL (prenode->next); + } + + sys_sem_s_signal (&pinfo->epiLock); + + /*free all epitem */ +#ifdef FREE_LIST_SIZE + fcurr = &flist; +#endif + for (i = 0; i < icnt; i++) + { +#ifdef FREE_LIST_SIZE + if ((i % FREE_LIST_SIZE) == 0 && i) + { + fcurr = fcurr->next; + if (fcurr == NULL) + { + NSSOC_LOGERR ("freelist invalid NULL, fd=%d icnt=%u i=%u", + pinfo->fd, icnt, i); + break; + } + } + epi = + ep_list_entry (fcurr->node[i % FREE_LIST_SIZE], struct epitem, + fllink); +#else + epi = ep_list_entry (node_arry[i], struct epitem, fllink); +#endif + ep = (struct eventpoll *) ADDR_SHTOL (epi->ep); + if (ep) + { + sys_arch_lock_with_pid (&ep->sem); + /* Here don't use epi you find before, use fd and ep to find the epi again.that is multithread safe */ + tepi = nsep_find_ep (ep, pinfo->fd); + /*record the exception log */ + if (epi != tepi) + { + NSSOC_LOGERR ("remove fd:%d epi:%p tepi:%p erro maybe happen", + pinfo->fd, epi, tepi); + } + /*if tepi is null, epi maybe free by nsep_close_epfd, so no need to free again */ + if (tepi) + { + nsep_epctl_triggle (tepi, pinfo, nstack_ep_triggle_del); + sys_arch_lock_with_pid (&ep->lock); + (void) nstack_ep_unlink (ep, tepi); + sys_sem_s_signal (&ep->lock); + + nsep_free_epitem (epi); + } + sys_sem_s_signal (&ep->sem); + } + } +#ifdef FREE_LIST_SIZE + for (fcurr = flist.next; fcurr; fcurr = flist.next) + { + flist.next = fcurr->next; + free (fcurr); + } +#else + free (node_arry); +#endif + return; +} + +void +nsep_close_epfd (struct eventpoll *ep) +{ + + if (!ep) + return; + + struct epitem *epi = NULL; + struct ep_rb_node *node = NULL; + + sys_arch_lock_with_pid (&ep->sem); + while ((node = ep_rb_first (&ep->rbr))) + { + + epi = ep_rb_entry (node, struct epitem, rbn); + int ret = nsep_epctl_del (ep, epi); + + if (ret) + { + NSSOC_LOGERR + ("nstack epctl del fail, will break to avoid dead loop]ep->fd=%d,epi->fd=%d", + ep->epfd, epi->fd); + break; + } + } + sys_sem_s_signal (&ep->sem); + nsep_free_eventpoll (ep); +} + +static inline int +nsp_epoll_close_kernel_fd (int sock, nsep_epollInfo_t * epInfo) +{ + NSSOC_LOGINF ("fd=%d,type=%d", sock, epInfo->fdtype); + int ret = 0; + nsep_remove_epfd (epInfo); + + u32_t pid = get_sys_pid (); + sys_arch_lock_with_pid (&epInfo->freeLock); + int left_count = nsep_del_last_pid (&epInfo->pidinfo, pid); + sys_sem_s_signal (&epInfo->freeLock); + if (-1 == left_count) + { + NSSOC_LOGERR ("pid not exist]fd=%d,type=%d,pid=%d", sock, + epInfo->fdtype, pid); + } + + if (0 == left_count) + { + ret = nsep_free_epinfo (epInfo); + NSSOC_LOGINF ("epinfo removed]fd=%d,type=%d", sock, epInfo->fdtype); + } + + return ret; +} + +static inline int +nsp_epoll_close_spl_fd (int sock, nsep_epollInfo_t * epInfo) +{ + NSSOC_LOGINF ("fd=%d,type=%d", sock, epInfo->fdtype); + nsep_remove_epfd (epInfo); + return 0; +} + +static inline int +nsp_epoll_close_ep_fd (int sock, nsep_epollInfo_t * epInfo) +{ + struct eventpoll *ep = ADDR_SHTOL (epInfo->ep); + u32_t pid = get_sys_pid (); + NSSOC_LOGINF ("fd:%d is epoll fd ep:%p]", sock, ep); + sys_arch_lock_with_pid (&epInfo->freeLock); + int left_count = nsep_del_last_pid (&epInfo->pidinfo, pid); + sys_sem_s_signal (&epInfo->freeLock); + if (0 == left_count) + { + epInfo->ep = NULL; + nsep_close_epfd (ep); + nsep_free_epinfo (epInfo); + } + return 0; +} + +int +nsep_epoll_close (int sock) +{ + int ret = 0; + int modInx = 0; + int flag = 0; + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (sock); + if (!epInfo) + { + NSSOC_LOGDBG ("epollsock close sock:%d is not exist", sock); + return 0; + } + + nsep_set_infoSockMap (sock, NULL); + + if (NSTACK_EPOL_FD == epInfo->fdtype) + { + return nsp_epoll_close_ep_fd (sock, epInfo); + } + + nstack_each_modInx (modInx) + { + if (0 == (epInfo->epaddflag & (1 << modInx))) + { + flag = 1; + } + } + /*if no stack reference the epinfo, just free epInfo, + *else wait until the stack closed completely + */ + if (0 == flag) + { + ret = nsp_epoll_close_kernel_fd (sock, epInfo); + } + else + { + ret = nsp_epoll_close_spl_fd (sock, epInfo); + } + return ret; +} + +void +nsep_set_infoSockMap (int sock, nsep_epollInfo_t * info) +{ + nsep_epollManager_t *manager = nsep_getManager (); + if (NULL == manager->infoSockMap) + return; + + if (sock < 0 || (u32_t) sock >= NSTACK_KERNEL_FD_MAX) + return; + + manager->infoSockMap[sock] = info; +} + +nsep_epollInfo_t * +nsep_get_infoBySock (int sock) +{ + nsep_epollManager_t *manager = nsep_getManager (); + if ((NULL == manager) || (NULL == manager->infoSockMap)) + return NULL; + + if (sock < 0 || (u32_t) sock >= NSTACK_KERNEL_FD_MAX) + return NULL; + + return manager->infoSockMap[sock]; +} + +int +nsep_alloc_infoWithSock (int nfd) +{ + + nsep_epollInfo_t *epInfo = NULL; + + if (!NSEP_IS_SOCK_VALID (nfd)) + { + return -1; + } + + if (-1 == nsep_alloc_epinfo (&epInfo)) + { + NSSOC_LOGERR ("Alloc share info fail,[return]"); + return -1; + } + + epInfo->fd = nfd; + + nsep_set_infoSockMap (nfd, epInfo); + + return 0; +} + +void +nsep_set_infoProtoFD (int fd, int modInx, int protoFD) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return; + + if (modInx < 0 || modInx >= NSTACK_MAX_MODULE_NUM) + return; + + epInfo->protoFD[modInx] = protoFD; +} + +int +nsep_get_infoProtoFD (int fd, int modInx) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return -1; + + return epInfo->protoFD[modInx]; +} + +void +nsep_set_infomdix (int fd, int rmidx) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return; + + epInfo->rmidx = rmidx; +} + +int +nsep_get_infoMidx (int fd) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return -1; + + return epInfo->rmidx; +} + +void +nsep_set_infoRlfd (int fd, int rlfd) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return; + + epInfo->rlfd = rlfd; +} + +int +nsep_get_infoRlfd (int fd) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return -1; + + return epInfo->rlfd; +} + +void +nsep_set_infoSleepTime (int fd, u32 sleepTime) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return; + + epInfo->sleepTime = sleepTime; +} + +int +nsep_get_infoSleepTime (int fd) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return -1; + + return epInfo->sleepTime; +} + +void +nsep_set_infoEp (int fd, struct eventpoll *ep) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return; + + epInfo->ep = (struct eventpoll *) ADDR_LTOSH (ep); + epInfo->fdtype = NSTACK_EPOL_FD; +} + +struct eventpoll * +nsep_get_infoEp (int fd) +{ + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (fd); + + if (NULL == epInfo) + return NULL; + + return (struct eventpoll *) ADDR_SHTOL (epInfo->ep); +} + +int +nsep_free_infoWithSock (int nfd) +{ + if ((u32_t) nfd >= NSTACK_KERNEL_FD_MAX || nfd < 0) + return -1; + + nsep_epollInfo_t *info = nsep_get_infoBySock (nfd); + + if (NULL == info) + return 0; + + nsep_set_infoSockMap (nfd, NULL); + + NSSOC_LOGDBG ("nsep_free_infoWithSock info:%p, nfd:%d", info, nfd); + /* If this not just used by linux, it should be freed in stack-x */ + if (-1 == nsep_free_epinfo (info)) + { + NSSOC_LOGERR ("Error to free ep info"); + return -1; + } + return 0; +} + +/** + * @Function nsep_init_infoSockMap + * @Description initial map of epoll info and socket + * @param none + * @return 0 on success, -1 on error + */ +int +nsep_init_infoSockMap () +{ + nsep_epollManager_t *manager = nsep_getManager (); + nsep_epollInfo_t **map = + (nsep_epollInfo_t **) malloc (NSTACK_KERNEL_FD_MAX * + sizeof (nsep_epollInfo_t *)); + + if (!map) + { + NSSOC_LOGERR ("malloc epInfoPool fail"); + return -1; + } + + u32_t iindex; + for (iindex = 0; iindex < NSTACK_KERNEL_FD_MAX; iindex++) + { + map[iindex] = NULL; + } + + manager->infoSockMap = map; + + return 0; +} + +NSTACK_STATIC mzone_handle +nsep_ring_lookup (char *name) +{ + if (NULL == name) + { + NSSOC_LOGERR ("param error]name=%p", name); + return NULL; + } + + nsfw_mem_name mem_name; + if (EOK != STRCPY_S (mem_name.aname, sizeof (mem_name.aname), name)) + { + NSSOC_LOGERR ("Error to lookup ring by name, strcpy fail]name=%s", + name); + return NULL; + } + mem_name.enowner = NSFW_PROC_MAIN; + mem_name.entype = NSFW_SHMEM; + + return nsfw_mem_ring_lookup (&mem_name); +} + +NSTACK_STATIC mzone_handle +nsep_attach_shmem (char *name) +{ + if (NULL == name) + { + NSSOC_LOGERR ("param error]name=%p", name); + return NULL; + } + + nsfw_mem_name mem_name; + int retVal = STRCPY_S (mem_name.aname, sizeof (mem_name.aname), name); + if (EOK != retVal) + { + NSSOC_LOGERR ("STRCPY_S failed]"); + return NULL; + } + mem_name.enowner = NSFW_PROC_MAIN; + mem_name.entype = NSFW_SHMEM; + + return nsfw_mem_zone_lookup (&mem_name); +} + +NSTACK_STATIC int +nsep_attach_infoMem () +{ + mzone_handle hdl = nsep_attach_shmem (MP_NSTACK_EPOLL_INFO_NAME); + if (NULL == hdl) + return -1; + + nsep_epollManager_t *manager = nsep_getManager (); + manager->infoPool.pool = (nsep_epollInfo_t *) hdl; + + hdl = nsep_ring_lookup (MP_NSTACK_EPINFO_RING_NAME); + if (NULL == hdl) + { + NSSOC_LOGERR ("Fail to loock up epoll info ring]name=%s", + MP_NSTACK_EPINFO_RING_NAME); + return -1; + } + + manager->infoPool.ring = hdl; + + return 0; +} + +NSTACK_STATIC int +nsep_attach_epItemMem () +{ + mzone_handle hdl = nsep_attach_shmem (MP_NSTACK_EPITEM_POOL); + if (NULL == hdl) + return -1; + + nsep_epollManager_t *manager = nsep_getManager (); + manager->epitemPool.pool = (struct epitem *) hdl; + + hdl = nsep_ring_lookup (MP_NSTACK_EPITEM_RING_NAME); + if (NULL == hdl) + { + NSSOC_LOGERR ("Fail to loock up epoll info ring]name=%s", + MP_NSTACK_EPITEM_RING_NAME); + return -1; + } + + manager->epitemPool.ring = hdl; + + return 0; +} + +NSTACK_STATIC int +nsep_attach_eventpollMem () +{ + mzone_handle hdl = nsep_attach_shmem (MP_NSTACK_EVENTPOLL_POOL); + if (NULL == hdl) + return -1; + + nsep_epollManager_t *manager = nsep_getManager (); + manager->epollPool.pool = (struct eventpoll *) hdl; + + hdl = nsep_ring_lookup (MP_NSTACK_EVENTPOOL_RING_NAME); + if (NULL == hdl) + { + NSSOC_LOGERR ("Fail to loock up epoll info ring]name=%s", + MP_NSTACK_EVENTPOOL_RING_NAME); + return -1; + } + + manager->epollPool.ring = hdl; + + return 0; +} + +/* epinfo add pid in parent */ +void +nsep_fork_parent_proc (u32_t ppid, u32_t cpid) +{ + nsep_epollManager_t *manager = nsep_getManager (); + if (NULL == manager->infoSockMap) + { + NSSOC_LOGERR ("infoSockMap is NULL]ppid=%d,cpid=%d", ppid, cpid); + return; + } + + nstack_fd_Inf *fdInf = NULL; + nsep_epollInfo_t *epinfo = NULL; + int pos; + for (pos = 0; (u32_t) pos < NSTACK_KERNEL_FD_MAX; pos++) + { + epinfo = manager->infoSockMap[pos]; + if (epinfo) + { + fdInf = nstack_getValidInf (pos); + if (fdInf) + { + if (((u32_t) (fdInf->type)) & SOCK_CLOEXEC) + { + NSSOC_LOGINF ("fd is SOCK_CLOEXEC]fd=%d,ppid=%d.cpid=%d", + pos, ppid, cpid); + continue; + } + } + + if (nsep_add_pid (&epinfo->pidinfo, cpid) != 0) + { + NSSOC_LOGERR ("epinfo add pid failed]fd=%d,ppid=%d.cpid=%d", + pos, ppid, cpid); + } + else + { + NSSOC_LOGDBG ("epinfo add pid ok]fd=%d,ppid=%d.cpid=%d", pos, + ppid, cpid); + } + } + } +} + +/* check is pid exist in child,if no,detach epinfo*/ +void +nsep_fork_child_proc (u32_t ppid) +{ + nsep_epollManager_t *manager = nsep_getManager (); + if (NULL == manager->infoSockMap) + { + NSSOC_LOGERR ("epinfi sockmap not be create"); + return; + } + + u32_t cpid = get_sys_pid (); + nsep_epollInfo_t *epinfo = NULL; + int pos; + for (pos = 0; (u32_t) pos < NSTACK_KERNEL_FD_MAX; pos++) + { + epinfo = manager->infoSockMap[pos]; + if (epinfo) + { + if (!nsep_is_pid_exist (&epinfo->pidinfo, cpid)) + { + NSSOC_LOGINF + ("unuse epinfo,happen in SOCK_CLOEXEC,!FD_OPEN,parent coredump]fd=%d,epinfo=%p,ppid=%d,cpid=%d", + pos, epinfo, ppid, cpid); + nsep_set_infoSockMap (pos, NULL); + } + } + } +} + +int +nsep_attach_memory () +{ + typedef int (*nsep_attachMemFunc_t) (void); + nsep_attachMemFunc_t attachFuncs[] = { nsep_attach_infoMem, + nsep_attach_epItemMem, + nsep_attach_eventpollMem + }; + + int i = 0; + for (i = 0; + i < (int) (sizeof (attachFuncs) / sizeof (nsep_attachMemFunc_t)); i++) + { + if (-1 == attachFuncs[i] ()) + return -1; + } + + return 0; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/nSocket/nstack/event/select/nstack_select.c b/src/nSocket/nstack/event/select/nstack_select.c new file mode 100644 index 0000000..bb43dbe --- /dev/null +++ b/src/nSocket/nstack/event/select/nstack_select.c @@ -0,0 +1,756 @@ +/* +* +* 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 "nstack_select.h" +#include "nstack_log.h" +#include "nsfw_base_linux_api.h" + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ +#ifdef NSTACK_SELECT_MODULE + +/*==============================================* + * project-wide global variables * + *----------------------------------------------*/ +extern void *nstack_select_thread (void *arg); +/*************select module***************************/ +struct select_module_info g_select_module = { + .inited = FALSE, +}; + +/*==============================================* + * routines' or functions' implementations * + *----------------------------------------------*/ +/***************************************************************************** +* Prototype : get_select_module +* Description : get_select_module +* Input : void +* Output : None +* Return Value : struct select_module_info * +* Calls : +* Called By : +*****************************************************************************/ +struct select_module_info * +get_select_module (void) +{ + return &g_select_module; +} + +/*split comm seclet entry to child mod select*/ +/***************************************************************************** +* Prototype : select_cb_split_by_mod +* Description : select_cb_split_by_module +* Input : i32 nfds +* fd_set *readfd +* fd_set *writefd +* fd_set *exceptfd +* struct select_entry *entry +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_cb_split_by_mod (i32 nfds, + fd_set * readfd, + fd_set * writefd, + fd_set * exceptfd, struct select_entry * entry) +{ + i32 inx; + i32 i; + i32 fd; + + for (i = 0; i < nfds; i++) + { + + /*not bound to any stack */ + for (inx = 0; inx < get_mode_num (); inx++) + { + if (!((readfd && FD_ISSET (i, readfd)) || + (writefd && FD_ISSET (i, writefd)) || + (exceptfd && FD_ISSET (i, exceptfd)))) + { + continue; + } + fd = select_get_modfd (i, inx); + + /*not create by nstack */ + if ((fd < 0) || (select_get_modindex (i) < 0)) + { + + if (inx != get_mode_linux_index ()) + { + continue; + } + fd = i; + nssct_create (fd, fd, inx); + } + else + { + if (select_get_modindex (i) != inx) + continue; + } + NSSOC_LOGDBG ("fd is valiable i= %d fd = %d index = %d\n", i, fd, + inx); + if ((readfd) && (FD_ISSET (i, readfd))) + { + NSTACK_FD_SET (fd, &(entry->cb[inx].nstack_readset)); + if (entry->cb[inx].count <= fd) + entry->cb[inx].count = fd + 1; + } + + if ((writefd) && (FD_ISSET (i, writefd))) + { + NSTACK_FD_SET (fd, &(entry->cb[inx].nstack_writeset)); + if (entry->cb[inx].count <= fd) + entry->cb[inx].count = fd + 1; + } + + if ((exceptfd) && (FD_ISSET (i, exceptfd))) + { + NSTACK_FD_SET (fd, &(entry->cb[inx].nstack_exceptset)); + if (entry->cb[inx].count <= fd) + entry->cb[inx].count = fd + 1; + } + } + } + + for (inx = 0; inx < get_mode_num (); inx++) + { + if (entry->cb[inx].count > 0) + { + entry->info.set_num++; + entry->info.index = inx; + } + } + return TRUE; +} + +/***************************************************************************** +* Prototype : select_add_cb +* Description : add cb to gloab list +* Input : struct select_entry *entry +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_add_cb (struct select_entry * entry) +{ + + if ((!entry)) + { + + return FALSE; + } + select_spin_lock (&g_select_module.lock); + + if (!g_select_module.entry_head) + { + g_select_module.entry_head = entry; + g_select_module.entry_tail = entry; + entry->next = NULL; + entry->prev = NULL; + } + else + { + g_select_module.entry_tail->next = entry; + entry->prev = g_select_module.entry_tail; + g_select_module.entry_tail = entry; + entry->next = NULL; + } + + select_spin_unlock (&g_select_module.lock); + select_sem_post (&g_select_module.sem); + return TRUE; +} + +/***************************************************************************** +* Prototype : select_rm_cb +* Description : rm the cb from gloab list +* Input : struct select_entry *entry +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_rm_cb (struct select_entry * entry) +{ + + if (!entry) + { + + return FALSE; + } + + select_spin_lock (&g_select_module.lock); + + if (g_select_module.entry_head == entry) + { + g_select_module.entry_head = entry->next; + + } + else if (entry->prev) + { + entry->prev->next = entry->next; + } + + if (g_select_module.entry_tail == entry) + { + g_select_module.entry_tail = entry->prev; + } + else if (entry->next) + { + entry->next->prev = entry->prev; + } + + entry->next = NULL; + entry->prev = NULL; + + select_spin_unlock (&g_select_module.lock); + return TRUE; +} + +/*get fd set from entrys*/ +/***************************************************************************** +* Prototype : select_thread_get_fdset +* Description : get module listening fd form gloab list +* Input : nstack_fd_set *readfd +* nstack_fd_set *writefd +* nstack_fd_set *exceptfd +* struct select_module_info *module +* i32 inx +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_thread_get_fdset (nstack_fd_set * readfd, + nstack_fd_set * writefd, + nstack_fd_set * exceptfd, + struct select_module_info * module, i32 inx) +{ + + struct select_entry *tmp; + i32 nfds = 0; + int retVal; + + if (!module) + { + return FALSE; + } + + retVal = NSTACK_FD_ZERO (readfd); + retVal |= NSTACK_FD_ZERO (writefd); + retVal |= NSTACK_FD_ZERO (exceptfd); + if (EOK != retVal) + { + NSSOC_LOGERR ("NSTACK_FD_ZERO MEMSET_S failed]ret=%d", retVal); + return FALSE; + } + + select_spin_lock (&module->lock); + for (tmp = module->entry_head; NULL != tmp; tmp = tmp->next) + { + if (tmp->cb[inx].count <= 0) + { + continue; + } + + NSTACK_FD_OR (readfd, &tmp->cb[inx].nstack_readset); + NSTACK_FD_OR (writefd, &tmp->cb[inx].nstack_writeset); + NSTACK_FD_OR (exceptfd, &tmp->cb[inx].nstack_exceptset); + if (nfds < tmp->cb[inx].count) + { + nfds = tmp->cb[inx].count; + } + } + select_spin_unlock (&module->lock); + + return nfds; +} + +/***************************************************************************** +* Prototype : select_thread_set_fdset +* Description : set ready event to gloab list +* Input : i32 nfds +* nstack_fd_set *readfd +* nstack_fd_set *writefd +* nstack_fd_set *exceptfd +* struct select_module_info *module +* i32 inx +* i32 err +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_thread_set_fdset (i32 nfds, + nstack_fd_set * readfd, + nstack_fd_set * writefd, + nstack_fd_set * exceptfd, + struct select_module_info * module, i32 inx, i32 err) +{ + + struct select_entry *tmp; + + if (!module) + { + return FALSE; + } + + select_spin_lock (&module->lock); + for (tmp = module->entry_head; NULL != tmp; tmp = tmp->next) + { + if (tmp->cb[inx].count <= 0) + { + continue; + } + + if (nfds < 0) + { + tmp->ready.readyset = nfds; + tmp->ready.select_errno = err; + continue; + } + NSSOC_LOGDBG ("readyset=%d,index=%d", tmp->ready.readyset, inx); + entry_module_fdset (tmp, nfds, readfd, writefd, exceptfd, inx); + } + select_spin_unlock (&module->lock); + return TRUE; + +} + +/***************************************************************************** +* Prototype : select_event_post +* Description : when event ready post sem to awaik nstack_select +* Input : struct select_module_info *module +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +select_event_post (struct select_module_info *module) +{ + struct select_entry *tmp; + int inx; + select_spin_lock (&module->lock); + for (tmp = module->entry_head; NULL != tmp; tmp = tmp->next) + { + + if ((tmp->ready.readyset != 0)) + { + for (inx = 0; inx < get_mode_num (); inx++) + { + tmp->cb[inx].count = 0; + } + NSSOC_LOGDBG ("readyset=%d", tmp->ready.readyset); + select_sem_post (&tmp->sem); + } + } + select_spin_unlock (&module->lock); +} + +/*set select_event function*/ +/***************************************************************************** +* Prototype : select_module_init +* Description : init select module +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_module_init () +{ + i32 i; + pthread_t select_thread_id; + i32 retval; + + if (fdmapping_init () < 0) + { + goto ERR_RET; + } + + g_select_module.default_mod = get_mode_linux_index (); + g_select_module.default_fun = nsfw_base_select; + + /*regist select fun */ + for (i = 0; i < get_mode_num (); i++) + { + g_select_module.get_select_fun_nonblock[i] = + nstack_module_ops (i)->pfselect; + } + + select_sem_init (&g_select_module.sem, 0, 0); + select_spin_lock_init (&g_select_module.lock); + + if (pthread_create (&select_thread_id, NULL, nstack_select_thread, NULL)) + { + + goto ERR_RET; + } + + retval = pthread_setname_np (select_thread_id, "nstack_select"); + if (retval) + { + /*set thread name failed */ + } + + g_select_module.inited = TRUE; + g_select_module.entry_head = g_select_module.entry_tail = NULL; + return TRUE; + +ERR_RET: + + return FALSE; +} + +/***************************************************************************** +* Prototype : entry_module_fdset +* Description : set event +* Input : struct select_entry *entry +* i32 fd_size +* nstack_fd_set *readfd +* nstack_fd_set *writefd +* nstack_fd_set *exceptfd +* i32 inx +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +entry_module_fdset (struct select_entry *entry, + i32 fd_size, + nstack_fd_set * readfd, + nstack_fd_set * writefd, + nstack_fd_set * exceptfd, i32 inx) +{ + i32 i; + i32 fd; + + for (i = 0; i < fd_size; i++) + { + fd = select_get_commfd (i, inx); + if (fd < 0) + { + continue; + } + if (NSTACK_FD_ISSET (i, readfd) + && NSTACK_FD_ISSET (i, &entry->cb[inx].nstack_readset)) + { + FD_SET (fd, &entry->ready.readset); + entry->ready.readyset++; + NSSOC_LOGDBG ("readyset is %d", entry->ready.readyset); + } + + if (NSTACK_FD_ISSET (i, writefd) + && NSTACK_FD_ISSET (i, &entry->cb[inx].nstack_writeset)) + { + FD_SET (fd, &entry->ready.writeset); + entry->ready.readyset++; + NSSOC_LOGDBG ("writeset is %d", entry->ready.readyset); + } + + if (NSTACK_FD_ISSET (i, exceptfd) + && NSTACK_FD_ISSET (i, &entry->cb[inx].nstack_exceptset)) + { + FD_SET (fd, &entry->ready.exceptset); + entry->ready.readyset++; + NSSOC_LOGDBG ("exceptset is %d", entry->ready.readyset); + } + } + +} + +/***************************************************************************** +* Prototype : select_scan +* Description : scan all modules to check event ready or not +* Input : struct select_entry *entry +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_scan (struct select_entry *entry) +{ + i32 inx; + i32 fd_size; + i32 ready; + nstack_fd_set *readfd; + nstack_fd_set *writefd; + nstack_fd_set *exceptfd; + struct timeval timeout; + + readfd = malloc (sizeof (nstack_fd_set)); + writefd = malloc (sizeof (nstack_fd_set)); + exceptfd = malloc (sizeof (nstack_fd_set)); + if ((!readfd) || (!writefd) || (!exceptfd)) + { + NSPOL_LOGERR ("malloc nstack_fd_set fail"); + FREE_FD_SET (readfd, writefd, exceptfd); + return -1; + } + for (inx = 0; inx < get_mode_num (); inx++) + { + + *readfd = entry->cb[inx].nstack_readset; + *writefd = entry->cb[inx].nstack_writeset; + *exceptfd = entry->cb[inx].nstack_exceptset; + fd_size = entry->cb[inx].count; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + if ((g_select_module.get_select_fun_nonblock[inx]) && (fd_size > 0)) + { + ready = + g_select_module.get_select_fun_nonblock[inx] (fd_size, + (fd_set *) readfd, + (fd_set *) writefd, + (fd_set *) exceptfd, + &timeout); + } + else + { + continue; + } + + if (ready > 0) + { + entry_module_fdset (entry, fd_size, readfd, writefd, exceptfd, inx); + } + else if (ready < 0) + { + entry->ready.readyset = ready; + entry->ready.select_errno = errno; + NSSOC_LOGERR ("select failed index = %d", inx); + FREE_FD_SET (readfd, writefd, exceptfd); + return FALSE; + } + + } + FREE_FD_SET (readfd, writefd, exceptfd); + return TRUE; +} + +/***************************************************************************** +* Prototype : lint_lock +* Description : avoid lint error +* Input : None +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +*****************************************************************************/ +static inline void +lint_lock () +{ + return; +} + +/***************************************************************************** +* Prototype : lint_unlock +* Description : avoid lint error +* Input : None +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +*****************************************************************************/ +static inline void +lint_unlock () +{ + return; +} + +/***************************************************************************** +* Prototype : nstack_select_thread +* Description : if gloab list not null scaning all modules ,need to think + about block mod +* Input : void *arg +* Output : None +* Return Value : void * +* Calls : +* Called By : +*****************************************************************************/ +void * +nstack_select_thread (void *arg) +{ + +#define SELECT_SLEEP_TIME 800 //us + + i32 inx; + nstack_fd_set *readfd; + nstack_fd_set *writefd; + nstack_fd_set *exceptfd; + i32 fd_size; + i32 ready; + i32 sleep_time = SELECT_SLEEP_TIME; + struct timeval timeout; + + lint_lock (); + + readfd = malloc (sizeof (nstack_fd_set)); + writefd = malloc (sizeof (nstack_fd_set)); + exceptfd = malloc (sizeof (nstack_fd_set)); + if ((!readfd) || (!writefd) || (!exceptfd)) + { + NSPOL_LOGERR ("malloc nstack_fd_set fail"); + FREE_FD_SET (readfd, writefd, exceptfd); + lint_unlock (); + return NULL; + } + + /*used nonblock need add block mod later */ + + for (;;) + { + /*wait app calling select no cong cpu */ + if (!g_select_module.entry_head) + { + select_sem_wait (&g_select_module.sem); + } + + for (inx = 0; inx < get_mode_num (); inx++) + { + + fd_size = + select_thread_get_fdset (readfd, writefd, exceptfd, + &g_select_module, inx); + if (fd_size <= 0) + { + continue; + } + + if (g_select_module.get_select_fun_nonblock[inx]) + { + ready = + g_select_module.get_select_fun_nonblock[inx] (fd_size, + (fd_set *) + readfd, + (fd_set *) + writefd, + (fd_set *) + exceptfd, + &timeout); + } + else + { + continue; + } + + if (ready > 0) + { + select_thread_set_fdset (fd_size, readfd, writefd, exceptfd, + &g_select_module, inx, 0); + } + else if (ready < 0) + { + select_thread_set_fdset (ready, readfd, writefd, exceptfd, + &g_select_module, inx, errno); + NSSOC_LOGERR ("module[%d] select failed] ret = %d errno = %d", + inx, ready, errno); + lint_unlock (); + break; + } + + } + select_event_post (&g_select_module); + timeout.tv_sec = 0; + timeout.tv_usec = sleep_time; + lint_unlock (); + /*use linux select for timer */ + nsfw_base_select (1, NULL, NULL, NULL, &timeout); + } +} + +/***************************************************************************** +* Prototype : nssct_create +* Description : create a select record for eveny fd +* Input : i32 cfd +* i32 mfd +* i32 inx +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nssct_create (i32 cfd, i32 mfd, i32 inx) +{ + if (g_select_module.inited != TRUE) + { + return; + } + select_set_modfd (cfd, inx, mfd); + select_set_commfd (mfd, inx, cfd); +} + +/***************************************************************************** +* Prototype : nssct_close +* Description : rm the record +* Input : i32 cfd +* i32 inx +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nssct_close (i32 cfd, i32 inx) +{ + if (g_select_module.inited != TRUE) + { + return; + } + i32 mfd = select_get_modfd (cfd, inx); + select_set_modfd (cfd, inx, -1); + select_set_commfd (mfd, inx, -1); + select_set_index (cfd, -1); +} + +/***************************************************************************** +* Prototype : nssct_set_index +* Description : set select fd index +* Input : i32 fd +* i32 inx +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nssct_set_index (i32 fd, i32 inx) +{ + if (g_select_module.inited != TRUE) + { + return; + } + select_set_index (fd, inx); +} + +#endif /* NSTACK_SELECT_MODULE */ diff --git a/src/nSocket/nstack/event/select/select_adapt.c b/src/nSocket/nstack/event/select/select_adapt.c new file mode 100644 index 0000000..a9858e8 --- /dev/null +++ b/src/nSocket/nstack/event/select/select_adapt.c @@ -0,0 +1,339 @@ +/* +* +* 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 "select_adapt.h" + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ + +/*==============================================* + * project-wide global variables * + *----------------------------------------------*/ +i32 nstack_mod_fd[NSTACK_MAX_MODULE_NUM][NSTACK_SELECT_MAX_FD]; +struct select_fd_map_inf g_select_fd_map; + +/*==============================================* + * routines' or functions' implementations * + *----------------------------------------------*/ + +/***************************************************************************** +* Prototype : select_alloc +* Description : select_alloc +* Input : int size +* Output : None +* Return Value : void * +* Calls : +* Called By : +*****************************************************************************/ +void * +select_alloc (int size) +{ + + char *p; + if (size <= 0) + { + return NULL; + } + + p = malloc (size); + if (!p) + { + return NULL; + } + if (EOK != MEMSET_S (p, size, 0, size)) + { + free (p); + p = NULL; + } + + return p; +} + +/***************************************************************************** +* Prototype : select_free +* Description : select_free +* Input : char *p +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +select_free (char *p) +{ + + if (p) + { + free (p); + p = NULL; + } +} + +/***************************************************************************** +* Prototype : get_select_fdinf +* Description : get_select_fdinf +* Input : i32 fd +* Output : None +* Return Value : struct select_comm_fd_map * +* Calls : +* Called By : +*****************************************************************************/ +struct select_comm_fd_map * +get_select_fdinf (i32 fd) +{ + if ((fd < 0) || (fd >= NSTACK_SELECT_MAX_FD)) + { + return NULL; + } + return (&g_select_fd_map.fdinf[fd]); +} + +/***************************************************************************** +* Prototype : reset_select_fdinf +* Description : reset_select_fdinf +* Input : i32 fd +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +reset_select_fdinf (i32 fd) +{ + i32 i; + struct select_comm_fd_map *fdinf = get_select_fdinf (fd); + if (NULL == fdinf) + { + return; + } + fdinf->index = -1; + for (i = 0; i < NSTACK_MAX_MODULE_NUM; i++) + { + fdinf->mod_fd[i] = -1; + } +} + +/***************************************************************************** +* Prototype : select_get_modfd +* Description : select_get_modfd +* Input : i32 fd +* i32 inx +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_get_modfd (i32 fd, i32 inx) +{ + if ((fd < 0) || (fd >= NSTACK_SELECT_MAX_FD)) + { + return -1; + } + if ((inx < 0)) + { + return -1; + } + if (!g_select_fd_map.fdinf) + { + return FALSE; + } + return (g_select_fd_map.fdinf[fd].mod_fd[inx]); + +} + +/***************************************************************************** +* Prototype : select_set_modfd +* Description : select_set_modfd +* Input : i32 fd +* i32 inx +* i32 modfd +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_set_modfd (i32 fd, i32 inx, i32 modfd) +{ + if ((fd < 0) || (fd >= NSTACK_SELECT_MAX_FD)) + { + return -1; + } + if (!g_select_fd_map.fdinf) + { + return FALSE; + } + g_select_fd_map.fdinf[fd].mod_fd[inx] = modfd; + + return TRUE; +} + +/***************************************************************************** +* Prototype : select_get_modindex +* Description : select_get_modindex +* Input : i32 fd +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_get_modindex (i32 fd) +{ + if ((fd < 0) || (fd >= NSTACK_SELECT_MAX_FD)) + { + return -1; + } + return g_select_fd_map.fdinf[fd].index; +} + +/***************************************************************************** +* Prototype : select_get_commfd +* Description : select_get_commfd +* Input : i32 modfd +* i32 inx +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_get_commfd (i32 modfd, i32 inx) +{ + + if ((modfd < 0) || (modfd >= NSTACK_SELECT_MAX_FD)) + { + return -1; + } + return g_select_fd_map.modinf[inx].comm_fd[modfd]; +} + +/***************************************************************************** +* Prototype : select_set_commfd +* Description : select_set_commfd +* Input : i32 modfd +* i32 inx +* i32 fd +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_set_commfd (i32 modfd, i32 inx, i32 fd) +{ + if ((modfd < 0) || (modfd >= NSTACK_SELECT_MAX_FD)) + { + return -1; + } + if (!g_select_fd_map.modinf[inx].comm_fd) + { + return FALSE; + } + g_select_fd_map.modinf[inx].comm_fd[modfd] = fd; + + return TRUE; +} + +/***************************************************************************** +* Prototype : select_set_index +* Description : select_set_index +* Input : i32 fd +* i32 inx +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +select_set_index (i32 fd, i32 inx) +{ + if ((fd < 0) || (fd >= NSTACK_SELECT_MAX_FD)) + { + return -1; + } + if (!g_select_fd_map.fdinf) + { + return FALSE; + } + g_select_fd_map.fdinf[fd].index = inx; + return TRUE; +} + +/***************************************************************************** +* Prototype : fdmapping_init +* Description : fdmapping_init +* Input : void +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +fdmapping_init (void) +{ + int ret = FALSE; + int i, inx; + + g_select_fd_map.fdinf = + (struct select_comm_fd_map *) + select_alloc (sizeof (struct select_comm_fd_map) * NSTACK_SELECT_MAX_FD); + if (NULL == g_select_fd_map.fdinf) + { + goto err_return; + } + + for (i = 0; i < get_mode_num (); i++) + { + g_select_fd_map.modinf[i].comm_fd = + (i32 *) select_alloc (sizeof (i32) * NSTACK_SELECT_MAX_FD); + if (NULL == g_select_fd_map.modinf[i].comm_fd) + { + goto err_return; + } + } + + for (i = 0; i < NSTACK_SELECT_MAX_FD; i++) + { + reset_select_fdinf (i); + } + + for (inx = 0; inx < get_mode_num (); inx++) + { + for (i = 0; i < NSTACK_SELECT_MAX_FD; i++) + { + select_set_commfd (i, inx, -1); + + } + } + + ret = TRUE; + return ret; +err_return: + + select_free ((char *) g_select_fd_map.fdinf); + for (i = 0; i < get_mode_num (); i++) + { + select_free ((char *) g_select_fd_map.modinf[i].comm_fd); + } + + return ret; +} diff --git a/src/nSocket/nstack/nstack.c b/src/nSocket/nstack/nstack.c new file mode 100644 index 0000000..2de167d --- /dev/null +++ b/src/nSocket/nstack/nstack.c @@ -0,0 +1,833 @@ +/* +* +* 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 +#include "nstack.h" +#include +#include +#include +#include +#include "common_mem_buf.h" +#include "common_mem_api.h" +#include "nstack_eventpoll.h" +#include "nstack_socket.h" +#include "nstack_securec.h" +#include "nsfw_init.h" +#include "nstack_share_res.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_ps_mem_api.h" +#include "nsfw_ps_api.h" +#include "nsfw_recycle_api.h" +#include "nstack_fd_mng.h" +#include "nstack_info_parse.h" +#include "nstack_dmm_adpt.h" +#include "nstack_rd_mng.h" +#include "nstack_rd.h" +#include "nstack_module.h" +#include "nstack_select.h" +#include "common_func.h" + +#define NSTACK_EVENT_MEN_MAXLEN (sizeof(struct eventpoll_pool) + NSTACK_MAX_EPOLL_NUM * sizeof(struct eventpoll_entry)) +#define NSTACK_EPITEM_MEN_MAXLEN (sizeof(struct epitem_pool) + NSTACK_MAX_EPITEM_NUM *sizeof(struct epitem_entry)) +/* *INDENT-OFF* */ +nStack_info_t g_nStackInfo = { + .hasInited = NSTACK_MODULE_INIT, + .fwInited = NSTACK_MODULE_INIT, + .moduleload = NSTACK_MODULE_INIT, + .load_mutex = PTHREAD_MUTEX_INITIALIZER, + .lk_sockPoll = NULL, + .pid = 0, + .fork_lock = {0}, + .ikernelfdmax = NSTACK_MAX_SOCK_NUM, + }; + +/*if this flag was set, maybe all socket interface called during initializing*/ +__thread int g_tloadflag = 0; + +/*check init stack*/ +#define NSTACK_INIT_STATE_CHECK_RET(state) do {\ + if ((state) == NSTACK_MODULE_SUCCESS) \ + { \ + return 0; \ + } \ + if ((state) == NSTACK_MODULE_FAIL) \ + { \ + return -1; \ + } \ +}while(0); + + + +int +nstack_timeval2msec (struct timeval *pTime, u64_t * msec) +{ + if (pTime->tv_sec < 0 || pTime->tv_usec < 0) + { + NSSOC_LOGERR ("time->tv_sec is nagative"); + return -1; + } + + if (NSTACK_MAX_U64_NUM / 1000 < (u64_t) pTime->tv_sec) + { + NSSOC_LOGERR ("tout.tv_sec is too large]tout.tv_sec=%lu", + pTime->tv_sec); + return -1; + } + u64_t sec2msec = 1000 * pTime->tv_sec; + u64_t usec2msec = (u64_t) pTime->tv_usec / 1000; + + if (NSTACK_MAX_U64_NUM - sec2msec < usec2msec) + { + NSSOC_LOGERR + ("nsec2msec plus sec2usec is too large]usec2msec=%lu,usec2msec=%lu", + usec2msec, sec2msec); + return -1; + } + + *msec = sec2msec + usec2msec; + return 0; +} + +int +nstack_current_time2msec (u64_t * msec) +{ + struct timespec tout; + if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &tout))) + { + NSSOC_LOGERR ("Failed to get time, errno = %d", errno); + } + + if (NSTACK_MAX_U64_NUM / 1000 < (u64_t) tout.tv_sec) + { + NSSOC_LOGERR ("tout.tv_sec is too large]tout.tv_sec=%lu", tout.tv_sec); + return -1; + } + u64_t sec2msec = 1000 * tout.tv_sec; + u64_t nsec2msec = (u64_t) tout.tv_nsec / 1000000; + + if (NSTACK_MAX_U64_NUM - sec2msec < nsec2msec) + { + NSSOC_LOGERR + ("nsec2msec plus sec2usec is too large]nsec2msec=%lu,usec2msec=%lu", + nsec2msec, sec2msec); + return -1; + } + + *msec = sec2msec + nsec2msec; + + return 0; +} + + +int +nstack_sem_timedwait (sem_t * pSem, u64_t abs_timeout /*ms */ ) +{ + int retVal; + + u64_t starttime, endtime; + +#define FAST_SLEEP_TIME 10000 +#define SLOW_SLEEP_TIME 500000 +#define FAST_RETRY_COUNT 100 + unsigned int retry_count = 0; + + if (nstack_current_time2msec (&starttime)) + { + errno = ETIMEDOUT; + return -1; + } + + while (1) + { + retVal = sem_trywait (pSem); + + if (nstack_current_time2msec (&endtime)) + { + errno = ETIMEDOUT; + return -1; + } + + /*when get event we return the time cost */ + if (retVal == 0) + { + return (endtime - starttime); + } + /*when time out it return 0 */ + if (endtime < starttime || (endtime - starttime) > abs_timeout) + { + errno = ETIMEDOUT; + return abs_timeout; + } + + /* app calling setsockopt to set time */ + if (retry_count < FAST_RETRY_COUNT) + { + sys_sleep_ns (0, FAST_SLEEP_TIME); + retry_count++; + } + else + { + sys_sleep_ns (0, SLOW_SLEEP_TIME); + } + } + +} + +/*epoll and select shouldnot get affected by system time change*/ +int +nstack_epoll_sem_timedwait (sem_t * pSem, u64_t abs_timeout /*ms */ , + long wait_time /*us */ ) +{ + int retVal; + + /* clock_gettime() get second variable is long, so here should use long */ + u64_t starttime, endtime; + +#define FAST_SLEEP_TIME 10000 +#define SLOW_SLEEP_TIME 500000 +#define FAST_RETRY_COUNT 100 + unsigned int retry_count = 0; + + if (nstack_current_time2msec (&starttime)) + { + errno = ETIMEDOUT; + return -1; + } + + while (1) + { + retVal = sem_trywait (pSem); + + if (retVal == 0) + { + return retVal; + } + + if (nstack_current_time2msec (&endtime)) + { + errno = ETIMEDOUT; + return -1; + } + + if (endtime < starttime || (endtime - starttime) > abs_timeout) + { + errno = ETIMEDOUT; + return -1; + } + + /*app calling setsockopt to set time */ + if (wait_time > 0) + { + long wait_sec; + long wait_nsec; + wait_sec = wait_time / 1000000; + wait_nsec = 1000 * (wait_time % 1000000); + sys_sleep_ns (wait_sec, wait_nsec); //g_sem_sleep_time + } + else if (retry_count < FAST_RETRY_COUNT) + { + sys_sleep_ns (0, FAST_SLEEP_TIME); + retry_count++; + } + else + { + sys_sleep_ns (0, SLOW_SLEEP_TIME); + } + } + +} + +NSTACK_STATIC inline char * +get_ver_head (char *version) +{ + const char *split = " "; + char *tmp = NULL; + char *next_pos = NULL; + + tmp = STRTOK_S (version, split, &next_pos); + if (NULL == tmp || NULL == next_pos) + { + return NULL; + } + + // version + tmp = STRTOK_S (next_pos, split, &next_pos); + if (NULL == tmp) + { + return NULL; + } + + return tmp; +} + +NSTACK_STATIC int +match_version (char *nstack_ver, char *my_ver) +{ + if ((NULL == nstack_ver || 0 == nstack_ver[0]) || + (NULL == my_ver || 0 == my_ver[0])) + { + NSSOC_LOGERR ("invalid input]"); + return 0; + } + + char *nstack_ver_head = NULL; + char *my_ver_head = NULL; + + char nstack_version[NSTACK_VERSION_LEN] = { 0 }; + char my_version[NSTACK_VERSION_LEN] = { 0 }; + + // !!!STRTOK_S will modify the original string, so use use temp for parameter + /* use STRCPY_S instead of MEMCPY_S to avoid invalid memory visit */ + if (EOK != STRCPY_S (nstack_version, sizeof (nstack_version), nstack_ver)) + { + return 0; + } + + nstack_ver_head = get_ver_head (nstack_version); + if (NULL == nstack_ver_head) + { + return 0; + } + + /*use STRCPY_S instead of MEMCPY_S to avoid invalid memory visit */ + if (EOK != STRCPY_S (my_version, sizeof (my_version), my_ver)) + { + return 0; + } + + my_ver_head = get_ver_head (my_version); + if (NULL == my_ver_head) + { + return 0; + } + + if (strlen (my_ver_head) != strlen (nstack_ver_head)) + { + return 0; + } + + + if (0 != strncmp (nstack_ver_head, my_ver_head, strlen (nstack_ver_head))) + { + return 0; + } + + return 1; +} + +NSTACK_STATIC inline void +set_unmatch_version (char *version, unmatch_ver_info_t * app_ver_info) +{ + int i = 0; + if (version == NULL || app_ver_info == NULL) + { + return; + } + + for (; i < MAX_UNMATCH_VER_CNT; i++) + { + if (app_ver_info[i].unmatch_count != 0) + { + if (0 == + strncmp (version, app_ver_info[i].lib_version, + NSTACK_VERSION_LEN - 1)) + { + app_ver_info[i].unmatch_count++; + return; + } + } + else + { + if (__sync_bool_compare_and_swap (&app_ver_info[i].unmatch_count, 0, 1)) + { + int retval = + STRNCPY_S (app_ver_info[i].lib_version, NSTACK_VERSION_LEN, + version, NSTACK_VERSION_LEN - 1); + if (EOK != retval) + { + NSSOC_LOGERR ("STRNCPY_S failed]ret=%d", retval); + return; + } + + get_current_time (app_ver_info[i].first_time_stamp, + LOG_TIME_STAMP_LEN); + return; + } + } + } +} + +NSTACK_STATIC inline void +check_main_version () +{ + char my_version[NSTACK_VERSION_LEN] = { 0 }; + nsfw_mem_name stname = { NSFW_SHMEM, NSFW_PROC_MAIN, {NSTACK_VERSION_SHM} }; + g_nStackInfo.nstack_version = nsfw_mem_zone_lookup (&stname); + + if (NULL == g_nStackInfo.nstack_version) + { + NSSOC_LOGERR ("can not get nstack version."); + return; + } + + if (EOK != STRCPY_S (my_version, sizeof (my_version), NSTACK_VERSION)) + { + NSSOC_LOGERR ("STRCPY_S failed"); + return; + } + + if (match_version (g_nStackInfo.nstack_version, my_version)) + { + return; + } + + NSSOC_LOGERR ("version not match]my version=%s, nStackMain_version=%s", + my_version, g_nStackInfo.nstack_version); + + /* record unmatched app version in snapshot */ + char *unmatch_app_version = + g_nStackInfo.nstack_version + NSTACK_VERSION_LEN; + + set_unmatch_version (my_version, + (unmatch_ver_info_t *) unmatch_app_version); +} + +int +nstack_init_shmem () +{ + + int deploytype = nstack_get_deploy_type (); + + if (deploytype > NSTACK_MODEL_TYPE1) + { + if (-1 == nsep_attach_memory ()) + { + return -1; + } + if (nstack_attach_share_res () != 0) + { + return -1; + } + } + else + { + if (nsep_create_memory () != 0) + { + return -1; + } + if (nstack_init_share_res () != 0) + { + return -1; + } + } + return 0; +} + + +/** + * This should be called only once + */ +NSTACK_STATIC int +nstack_init_mem (void) +{ + + int ret = ns_fail; + int initflag = 0; + int deploytype = nstack_get_deploy_type (); + /* record unmatched app version*/ + /* check lib version match - Begin */ + if (deploytype > NSTACK_MODEL_TYPE1) + { + check_main_version (); + initflag = 1; + } + + ret = nstack_init_shmem (); + if (ns_success != ret) + { + NSSOC_LOGERR ("nstack init shmem fail"); + return ns_fail; + } + + /*stack-x rd mng init*/ + ret = nstack_rd_mng_int(initflag); + if (ns_success != ret) + { + NSSOC_LOGERR("nstack_rd_mng_int fail"); + return ns_fail; + } + + /*rd info sys*/ + ret = nstack_rd_sys(); + if (ns_success != ret) + { + NSSOC_LOGERR("nstack rd sys fail"); + return ns_fail; + } + + (void)nstack_stack_module_init(); + + /*init select mod*/ + if(FALSE == select_module_init()){ + return ns_fail; + } + return ns_success; + /* The memory of the g_nStackInfo.lk_sockPoll was not released in the exception*/ +} + +void +nstack_fork_fd_local_lock_info (nstack_fd_local_lock_info_t * local_lock) +{ + if (local_lock->fd_ref.counter > 1) /* after fork, if fd ref > 1, need set it to 1 */ + { + local_lock->fd_ref.counter = 1; + } + common_mem_spinlock_init (&local_lock->close_lock); +} + +void +nstack_reset_fd_local_lock_info (nstack_fd_local_lock_info_t * local_lock) +{ + atomic_set (&local_lock->fd_ref, 0); + common_mem_spinlock_init (&local_lock->close_lock); + local_lock->fd_status = FD_CLOSE; +} + +common_mem_rwlock_t * +get_fork_lock () +{ + return &g_nStackInfo.fork_lock; +} + +NSTACK_STATIC int +nstack_init_fd_local_info () +{ + int iindex = 0; + nstack_fd_Inf *fdInf; + + g_nStackInfo.lk_sockPoll = (nstack_fd_Inf *) malloc (NSTACK_KERNEL_FD_MAX * sizeof (nstack_fd_Inf)); + if (!g_nStackInfo.lk_sockPoll) + { + NSSOC_LOGERR ("malloc nstack_fd_lock_info failed"); + return ns_fail; + } + + for (iindex = 0; iindex < (int) NSTACK_KERNEL_FD_MAX; iindex++) + { + fdInf = &g_nStackInfo.lk_sockPoll[iindex]; + nstack_reset_fdInf (fdInf); + } + + if (-1 == nsep_init_infoSockMap ()) + { + NSSOC_LOGERR ("malloc epInfoPool fail"); + if (g_nStackInfo.lk_sockPoll) + { + free (g_nStackInfo.lk_sockPoll); + g_nStackInfo.lk_sockPoll = NULL; + } + return ns_fail; + } + + return ns_success; +} + + + +/*design ensures that g_ksInfo is not write accessed at the same time. +only read is done simultaneously with no chance of other thread writing it. +so no protection needed.*/ +int +nstack_stack_init (void) +{ // Just need to create shared memory + int ret; + + ret = nstack_init_fd_local_info (); + if (ret != ns_success) + { + goto INIT_DONE; + } + + if (ns_fail == nstack_init_mem ()) + { + ret = ns_fail; + goto INIT_DONE; + } + + if (SYS_HOST_INITIAL_PID == get_sys_pid ()) + { + ret = ns_fail; + goto INIT_DONE; + } + + ret = ns_success; + +INIT_DONE: + + if (ns_success == ret) + { + NSSOC_LOGDBG ("success"); + } + else + { + NSSOC_LOGERR ("fail"); + } + return ret; +} + +int +nstack_for_epoll_init () +{ + NSSOC_LOGINF ("fork] init begin.."); + if (g_nStackInfo.pid != 0 && g_nStackInfo.pid != getpid ()) + { + NSSOC_LOGINF ("fork]g_nStackInfo.pid=%u,getpid=%d", g_nStackInfo.pid, + getpid ()); + + nstack_stack_module_init(); + } + return 0; +} + + + +void +signal_handler_app (int s) +{ + NSPOL_LOGERR ("Received signal exiting.]s=%d", s); + if (SIGHUP != s && SIGTERM != s) + { + nstack_segment_error (s); + } +} + +void +register_signal_handler_app () +{ + /* handle function should comply secure coding standard + here mask signal that will use in sigwait() */ + sigset_t waitset, oset; + if (0 != sigemptyset (&waitset)) + { + NSPOL_LOGERR ("sigemptyset failed"); + } + if (0 != sigaddset (&waitset, SIGRTMIN)) /* for timer */ + { + NSPOL_LOGERR ("sigaddset failed"); + } + if (0 != sigaddset (&waitset, SIGRTMIN + 2)) + { + NSPOL_LOGERR ("sigaddset failed"); + } + if (0 != pthread_sigmask (SIG_BLOCK, &waitset, &oset)) + { + NSPOL_LOGERR ("pthread_sigmask failed"); + } + + + struct sigaction s; + s.sa_handler = signal_handler_app; + if (0 != sigemptyset (&s.sa_mask)) + { + NSPOL_LOGERR ("sigemptyset failed."); + } + + s.sa_flags = (int) SA_RESETHAND; + + /* register sig handler for more signals */ + if (sigaction (SIGINT, &s, NULL) != 0) + { + NSPOL_LOGERR ("Could not register SIGINT signal handler."); + } + if (sigaction (SIGSEGV, &s, NULL) != 0) + { + NSPOL_LOGERR ("Could not register SIGSEGV signal handler."); + } + if (sigaction (SIGPIPE, &s, NULL) != 0) + { + NSPOL_LOGERR ("Could not register SIGPIPE signal handler."); + } + if (sigaction (SIGFPE, &s, NULL) != 0) + { + NSPOL_LOGERR ("Could not register SIGFPE signal handler."); + } + if (sigaction (SIGABRT, &s, NULL) != 0) + { + NSPOL_LOGERR ("Could not register SIGABRT signal handler."); + } + if (sigaction (SIGBUS, &s, NULL) != 0) + { + NSPOL_LOGERR ("Could not register SIGBUS signal handler."); + } + /* register sig handler for more signals */ + + +} + +int nstack_stack_module_load() +{ + /*check whether already inited*/ + NSTACK_INIT_STATE_CHECK_RET(g_nStackInfo.moduleload); + + /*lock for fork*/ + common_mem_rwlock_read_lock(get_fork_lock()); + + if (pthread_mutex_lock(&g_nStackInfo.load_mutex)){ + NSSOC_LOGERR("nstack mutex lock fail"); + common_mem_rwlock_read_unlock(get_fork_lock()); + return -1; + } + + NSTACK_INIT_STATE_CHECK_RET(g_nStackInfo.moduleload); + + NSTACK_THREAD_LOAD_SET(); + + if (0 != nstack_module_parse()) + { + NSSOC_LOGERR("nstack stack module parse fail"); + goto LOAD_FAIL; + } + + if (0 != nstack_register_module()) + { + NSSOC_LOGERR("nstack stack module parse fail"); + goto LOAD_FAIL; + } + + NSTACK_THREAD_LOAD_UNSET(); + g_nStackInfo.moduleload = NSTACK_MODULE_SUCCESS; + common_mem_rwlock_read_unlock(get_fork_lock()); + pthread_mutex_unlock(&g_nStackInfo.load_mutex); + return 0; + +LOAD_FAIL: + g_nStackInfo.moduleload = NSTACK_MODULE_FAIL; + NSTACK_THREAD_LOAD_UNSET(); + common_mem_rwlock_read_unlock(get_fork_lock()); + pthread_mutex_unlock(&g_nStackInfo.load_mutex); + return -1; +} + +int +nstack_app_init (void *ppara) +{ + NSSOC_LOGINF("nstack app init begin"); + + g_nStackInfo.ikernelfdmax = nstack_get_maxfd_id(nstack_get_fix_mid()); + + NSSOC_LOGINF("final max fd:%d", g_nStackInfo.ikernelfdmax); + + g_nStackInfo.pid = getpid (); + + /*if init already, just return success, if init fail before, just return err */ + if (NSTACK_MODULE_INIT != g_nStackInfo.hasInited) + { + NSSOC_LOGINF ("nstack app already init state:%d", + g_nStackInfo.hasInited); + return (NSTACK_MODULE_SUCCESS == + g_nStackInfo.hasInited ? ns_success : ns_fail); + } + + if (0 != nstack_stack_init ()) + { + NSSOC_LOGERR ("nstack stack init failed"); + g_nStackInfo.hasInited = NSTACK_MODULE_FAIL; + return ns_fail; + } + + g_nStackInfo.hasInited = NSTACK_MODULE_SUCCESS; + NSSOC_LOGINF ("nstack app init success end"); + return ns_success; +} + +/*nsocket call framework init fun*/ +int +nstack_fw_init () +{ + + int ret = ns_fail; + + if (NSTACK_MODULE_SUCCESS == g_nStackInfo.fwInited) + { + return ns_success; + } + + if (NSTACK_MODULE_INIT == g_nStackInfo.fwInited) + { + nstack_log_init_app(); + + if (0 != nstack_stack_module_load()) + { + NSSOC_LOGERR("nstack stack module load fail"); + g_nStackInfo.fwInited = NSTACK_MODULE_FAIL; + return -1; + } + + common_mem_rwlock_read_lock (get_fork_lock ()); + updata_sys_pid (); + u8 proc_type = NSFW_PROC_APP; + nsfw_mem_para stinfo = { 0 }; + + int deploytype = nstack_get_deploy_type(); + + if (deploytype == NSTACK_MODEL_TYPE1) + { + proc_type = NSFW_PROC_MAIN; + } + + stinfo.iargsnum = 0; + stinfo.pargs = NULL; + stinfo.enflag = (fw_poc_type)proc_type; + nstack_framework_setModuleParam(NSFW_MEM_MGR_MODULE, (void*)&stinfo); + nstack_framework_setModuleParam(NSFW_MGR_COM_MODULE, (void*) ((long long)proc_type)); + nstack_framework_setModuleParam(NSFW_PS_MODULE, (void*) ((long long)proc_type)); + nstack_framework_setModuleParam(NSFW_PS_MEM_MODULE, (void*) ((long long)proc_type)); + nstack_framework_setModuleParam(NSFW_RECYCLE_MODULE, (void*) ((long long)proc_type)); + NSTACK_THREAD_LOAD_SET(); + ret = nstack_framework_init(); + /*init tracing*/ + nstack_trace_init(0); + + if (ns_success == ret) + { + g_nStackInfo.fwInited = NSTACK_MODULE_SUCCESS; + } + else + { + g_nStackInfo.fwInited = NSTACK_MODULE_FAIL; + } + NSTACK_THREAD_LOAD_UNSET(); + common_mem_rwlock_read_unlock(get_fork_lock()); + } + + return ret; +} + +nstack_fd_local_lock_info_t * +get_fd_local_lock_info (int fd) +{ + if (!g_nStackInfo.lk_sockPoll) + { + return NULL; + } + + if (fd >= 0 && fd < (int) NSTACK_KERNEL_FD_MAX) + { + return &(g_nStackInfo.lk_sockPoll[fd].local_lock); + } + + return NULL; +} diff --git a/src/nSocket/nstack/nstack.h b/src/nSocket/nstack/nstack.h new file mode 100644 index 0000000..6d40a7b --- /dev/null +++ b/src/nSocket/nstack/nstack.h @@ -0,0 +1,121 @@ +/* +* +* 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 _NSTACK_H_ +#define _NSTACK_H_ + +#include +#include +#include +#include +#include +#include + +#include "nstack_log.h" +#include "nstack_module.h" +#include "nstack_fd_mng.h" + +#include "nstack_types.h" +#include "nstack_eventpoll.h" +#include "common_mem_api.h" +#include "nstack_select.h" + +#include +#include +#include +#include +#include "nstack_atomic.h" +#include "common_mem_spinlock.h" +#include "generic/common_mem_rwlock.h" + +#include "nsfw_mem_api.h" +#include "nsfw_recycle_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif + +#define NSTACK_PIDINFO "hw_nstack_pidinfo" + +typedef enum +{ + NSTACK_MODULE_INIT, + NSTACK_MODULE_SUCCESS, + NSTACK_MODULE_FAIL +} nstack_module_state; + +typedef struct +{ + nstack_module_state hasInited; /*nsocket inside init status */ + nstack_module_state fwInited; /*framework init status */ + nstack_module_state moduleload; /*framework init status */ + char pad1[2]; + + pthread_mutex_t load_mutex; + /* if a nstack_fd_Inf contains a valid linux kernel proFD, it will be allocated from this poll. + * Total size of the poll is NSTACK_MAX_SOCK_NUM, index range is [0, NSTACK_MAX_SOCK_NUM). + */ + nstack_fd_Inf *lk_sockPoll; + + common_mem_rwlock_t fork_lock; /* to ensure that there is no fd to create and close when fork */ + uint32_t pid; + char *nstack_version; + int checkEpollFD; + uint32_t ikernelfdmax; +} __attribute__ ((__packed__)) nStack_info_t; + +#define ENV_NSTACK_RD_CFG_PATH "NSTACK_RD_CFG_PATH" + +#define nstack_set_errno(no) errno = (no) + +extern nStack_info_t g_nStackInfo; +extern __thread int g_tloadflag; + +#define NSTACK_KERNEL_FD_MAX (g_nStackInfo.ikernelfdmax) +#define NSTACK_THREAD_LOAD_SET() (g_tloadflag = 1) +#define NSTACK_THREAD_LOAD_UNSET() (g_tloadflag = 0) +#define NSTACK_THREAD_LOADING() (g_tloadflag == 1) + +#define nstack_each_protoFDSt(modInx, fdInf, st) \ + for ((modInx) = 0; ((modInx) < nstack_get_modNum() && ((st) = nstack_get_protoFdSt((fdInf), modInx))); (modInx)++) + +extern int nstack_timeval2msec (struct timeval *pTime, u64_t * msec); +extern int nstack_current_time2msec (u64_t * msec); +extern int nstack_sem_timedwait (sem_t * pSem, u64_t abs_timeout /*ms */ ); +extern int nstack_epoll_sem_timedwait (sem_t * pSem, + u64_t abs_timeout /*ms */ , + long wait_time /*us */ ); +extern int nstack_app_init (void *ppara); +extern int nstack_fw_init (); + +nstack_fd_local_lock_info_t *get_fd_local_lock_info (int fd); +void nstack_fork_fd_local_lock_info (nstack_fd_local_lock_info_t * + local_lock); +void nstack_reset_fd_local_lock_info (nstack_fd_local_lock_info_t * + local_lock); +common_mem_rwlock_t *get_fork_lock (); +int nstack_for_epoll_init (); +int nstack_stack_module_load (); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/nSocket/nstack/nstack_fd_mng.c b/src/nSocket/nstack/nstack_fd_mng.c new file mode 100644 index 0000000..995b93a --- /dev/null +++ b/src/nSocket/nstack/nstack_fd_mng.c @@ -0,0 +1,240 @@ +/* +* +* 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 +#include +#include +#include +#include +#include + +#include "nstack.h" +#include "nstack_fd_mng.h" +#include "nstack_socket.h" +#include "nstack_securec.h" +#include "nstack_sockops.h" + +/* test_epollCtl_004_001_trial : both 32bit and 64bit members of 'ops' and 'conn' + need to reset, otherwise it will be invalid address in 32bit APP case */ +void +nstack_reset_fdInf (nstack_fd_Inf * fdInf) +{ + int loop; + + fdInf->isBound = NSTACK_FD_NOBIND; + fdInf->rlfd = -1; + fdInf->rmidx = -1; + fdInf->nxtfd = -1; + fdInf->fd = -1; + fdInf->attr = 0; + fdInf->ops = 0; /*opers of the fd, for save space we user opIdx here */ + fdInf->type = 0; /*the fd type like SOCK_STREAM|SOCK_NONBLOCK ... */ + + NSTACK_SET_FD_BLOKING (fdInf); + for (loop = 0; loop < NSTACK_MAX_MODULE_NUM; loop++) + { + fdInf->protoFD[loop].fd = -1; + fdInf->protoFD[loop].errCode = 0; + fdInf->protoFD[loop].pad = 0; + fdInf->protoFD[loop].liststate = NSTACK_NO_LISENING; + } + + nstack_reset_fd_local_lock_info (&(fdInf->local_lock)); + return; +} + +nstack_fd_Inf * +nstack_fd2inf (int fd) +{ + /*if nstack init not finished, just return null */ + if (NSTACK_MODULE_SUCCESS != g_nStackInfo.fwInited) + { + return NULL; + } + if (nstack_is_nstack_sk (fd) && g_nStackInfo.lk_sockPoll) + { + return &(g_nStackInfo.lk_sockPoll[fd]); + } + return NULL; +} + +void +nstack_set_protoFd (nstack_fd_Inf * fdInf, int modInx, int protofd) +{ + + if (protofd < nstack_get_minfd_id (modInx) + || protofd > nstack_get_maxfd_id (modInx)) + { + NSSOC_LOGERR ("module:%d protofd invalid] protofd=%d", modInx, protofd); + return; + } + + nstack_get_protoFd (fdInf, modInx) = protofd; + + nsep_set_infoProtoFD (fdInf->fd, modInx, protofd); + + nssct_create (fdInf->fd, protofd, modInx); + return; +} + +/* pass app info to struct netconn */ +void +nstack_set_app_info (nstack_fd_Inf * fdInf, int modInx) +{ + return; +} + +nstack_fd_Inf * +nstack_lk_fd_alloc_with_kernel (int nfd) +{ + nstack_fd_Inf *retInf = NULL; + + if ((nfd < 0) || (nfd >= (int) NSTACK_KERNEL_FD_MAX) + || (!g_nStackInfo.lk_sockPoll)) + { + NSSOC_LOGERR + ("nfd < 0 or nfd>= NSTACK_KERNEL_FD_MAX, parameter not valid"); + return NULL; + } + + retInf = &g_nStackInfo.lk_sockPoll[nfd]; + + if (FD_OPEN == retInf->local_lock.fd_status) + { + NSSOC_LOGERR ("nstack_lk_fd_alloc_with_kernel fd:%d already create", + nfd); + } + + retInf->fd = nfd; + if (-1 == nsep_alloc_infoWithSock (nfd)) + { + NSSOC_LOGERR ("Can't alloc epInfo for nfd=%d]", nfd); + nstack_reset_fdInf (retInf); + return NULL; + } + + nstack_set_protoFd (retInf, g_nstack_modules.fix_mid, nfd); + NSSOC_LOGDBG ("nfd=%d,retInf_fd=%d", nfd, retInf->fd); + return retInf; +} + +int +nstack_fd_free_with_kernel (nstack_fd_Inf * fdInf) +{ + int closeRet = 0; + ns_int32 fd; + + if (!fdInf) + { + NSSOC_LOGERR ("fdInf is NULL"); + return 0; + } + fd = fdInf->protoFD[nstack_get_fix_mid ()].fd; + nstack_reset_fdInf (fdInf); + + if (fd >= 0 && fd < (int) NSTACK_KERNEL_FD_MAX) + { + NSTACK_CAL_FUN (nstack_fix_mid_ops (), close, (fd), closeRet); + NSSOC_LOGINF ("close]fd=%d,ret=%d", fd, closeRet); + } + return closeRet; +} + +void +nstack_fork_init_parent (pid_t ppid) +{ + int fd; + nstack_fd_Inf *fdInf = NULL; + for (fd = 0; fd < (int) NSTACK_KERNEL_FD_MAX; fd++) + { + fdInf = nstack_getValidInf (fd); + if ((NULL != fdInf) && (!((u32_t) (fdInf->type) & SOCK_CLOEXEC))) + { + int i; + nstack_each_modInx (i) + { + if ((nstack_extern_deal (i).fork_parent_fd) + && (fdInf->protoFD[i].fd >= 0)) + { + nstack_extern_deal (i).fork_parent_fd (fdInf->protoFD[i].fd, + ppid); + } + } + } + } +} + +void +nstack_fork_init_child (pid_t ppid) +{ + pid_t cpid = updata_sys_pid (); + NSSOC_LOGDBG ("parent_pid=%d, child_pid=%d", ppid, cpid); + + nsfw_mgr_clr_fd_lock (); + if (FALSE == nsfw_recycle_fork_init ()) + { + NSFW_LOGERR ("init rec zone failed!]ppid=%d,cpid=%d", ppid, cpid); + } + + int i; + nstack_each_modInx (i) + { + if (nstack_extern_deal (i).fork_init_child) + { + nstack_extern_deal (i).fork_init_child (ppid, cpid); + } + } + + int pos; + nstack_fd_Inf *fdInf = NULL; + + for (pos = 0; pos < (int) NSTACK_KERNEL_FD_MAX; pos++) + { + fdInf = nstack_getValidInf (pos); + if (fdInf) + { + if (!((u32_t) (fdInf->type) & SOCK_CLOEXEC)) + { + nstack_fork_fd_local_lock_info (&fdInf->local_lock); + + nstack_each_modInx (i) + { + if ((nstack_extern_deal (i).fork_child_fd) + && (fdInf->protoFD[i].fd >= 0)) + { + nstack_extern_deal (i).fork_child_fd (fdInf-> + protoFD[i].fd, ppid, + cpid); + } + } + } + else + { + nstack_reset_fd_local_lock_info (&fdInf->local_lock); + nsep_set_infoSockMap (pos, NULL); + nstack_each_modInx (i) + { + if ((nstack_extern_deal (i).fork_free_fd) + && (fdInf->protoFD[i].fd >= 0)) + { + nstack_extern_deal (i).fork_free_fd (fdInf->protoFD[i].fd, + ppid, cpid); + } + } + } + } + } +} diff --git a/src/nSocket/nstack/nstack_fd_mng.h b/src/nSocket/nstack/nstack_fd_mng.h new file mode 100644 index 0000000..0b1cf8d --- /dev/null +++ b/src/nSocket/nstack/nstack_fd_mng.h @@ -0,0 +1,210 @@ +/* +* +* 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 __NSTACK_FD_MNG_H__ +#define __NSTACK_FD_MNG_H__ + +#include +#include "nstack_atomic.h" + +#include "types.h" +#include "nstack_module.h" +#include "nstack_types.h" +#include "nstack_eventpoll.h" +#include "common_mem_spinlock.h" +#include "common_mem_api.h" +#include "common_func.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define NSTACK_FDT_BLOCK_NOFFSET 10 +#define NSTACK_FDT_CONVERT_FLAG 0x40000000 /* flag set means nstack socket */ + +#define NSTACK_MAX_SOCK_NUM 8192 + +#define NSTACK_MAX_PID 65536 /* release sockets when app exit */ + +#ifndef AF_INET +#define AF_INET 2 +#endif + +#ifndef NSTACK_SOCKOPT_CHECK +#define NSTACK_SOCKOPT_CHECK +/* setsockopt level type*/ +enum +{ + NSTACK_SOCKOPT = 0xff02 +}; +/*setsockopt optname type*/ +enum +{ + NSTACK_SEM_SLEEP = 0X001 +}; +#endif +#define nstack_is_nstack_sk(fd) ((fd) >= 0 && ((fd) < (int)NSTACK_KERNEL_FD_MAX)) + +typedef enum __nstack_fd_Stat +{ + NSTACK_FD_INUSING, + NSTACK_FD_DISCARD +} nstack_fd_stat; + +#define NSTACK_BIND_SUCCESS 0 +#define NSTACK_LISTEN_SUCCESS 0 +#define NSTACK_LISTEN_FAIL 1 +#define NSTACK_BIND_FAIL 1 +#define NSTACK_LISENING 1 +#define NSTACK_NO_LISENING 0 + +#define NSTACK_FD_INIT (0) +#define NSTACK_FD_OPEN (1) +#define NSTACK_FD_CLOSE (2) + +#define NSTACK_FD_NOBIND (0) +#define NSTACK_FD_BIND (1) + +/* release sockets when app exit */ + +typedef struct +{ + ns_int32 fd; + ns_int32 errCode; + union + { + struct reslt + { + ns_int32 brslt:8; + ns_int32 lrslt:8; + ns_int32 resrv:16; + } rslt; + ns_int32 pad; + }; + ns_int32 liststate; +} __attribute__ ((__packed__)) nstack_protoFD_t; + +#define NSTACK_FD_ATTR_NONBLOKING 0x00000001 +#define NSTACK_FD_ATTR_EPOLL_SOCKET 0x00000002 +#define NSTACK_FD_ATTR_LISTEN_SOCKET 0x00000004 + +#define NSTACK_IS_FD_NONBLOKING(inf) ((inf)->attr & NSTACK_FD_ATTR_NONBLOKING) +#define NSTACK_SET_FD_NONBLOKING(inf) ((inf)->attr |= NSTACK_FD_ATTR_NONBLOKING) +#define NSTACK_SET_FD_BLOKING(inf) ((inf)->attr &= (~NSTACK_FD_ATTR_NONBLOKING)) + +#define NSTACK_IS_FD_EPOLL_SOCKET(inf) ((inf)->attr & NSTACK_FD_ATTR_EPOLL_SOCKET) +#define NSTACK_SET_FD_EPOLL_SOCKET(inf) ((inf)->attr |= NSTACK_FD_ATTR_EPOLL_SOCKET) +#define NSTACK_IS_FD_LISTEN_SOCKET(inf) ((inf)->attr & NSTACK_FD_ATTR_LISTEN_SOCKET) +#define NSTACK_SET_FD_LISTEN_SOCKET(inf) ((inf)->attr |= NSTACK_FD_ATTR_LISTEN_SOCKET) + +typedef struct +{ + atomic_t fd_ref; + common_mem_spinlock_t close_lock; + volatile int fd_status; +} nstack_fd_local_lock_info_t; +/* +fd_ref:the number of times the fd is used, when it is 0, should release fd resource +close_lock:lock for close and epoll +fd_status:when created, it is FD_OPEN;after close, it is FD_CLOSING;after release_fd, +it is FD_CLOSE. +- Begin */ +typedef enum +{ + FD_CLOSE, + FD_OPEN, + FD_CLOSING +} FD_STATUS; + +typedef enum +{ + NSTACK_STATE_CLOSE, + NSTACK_STATE_OPEN, + NSTACK_STATE_MAX +} nstack_fdstate; +typedef struct __nstack_fd_Inf +{ + ns_int32 rlfd; /*the protocl stack returned fd */ + ns_int32 rmidx; + ns_int32 nxtfd; + nstack_socket_ops *ops; /*opers of the fd, for save space we user opIdx here */ + ns_int32 type; /*the fd type like SOCK_STREAM|SOCK_NONBLOCK ... */ + ns_int32 stat; + ns_int32 fd; + ns_uint32 attr; /* attribute like non-blocking, listen socket , epoll socket.... */ + + nstack_protoFD_t protoFD[NSTACK_MAX_MODULE_NUM]; // where is protocol fd stores, index is module type + nstack_fd_local_lock_info_t local_lock; + /* if has bound to an addr */ + u8_t isBound; /*0:no call bind, 1: call bind */ + char last_reserve[2]; //reserve for update +} nstack_fd_Inf; + +#define nstack_set_router_protocol(_fdInf, _proto) \ + (_fdInf)->rmidx = (_proto); \ + nsep_set_infomdix((_fdInf)->fd, (_proto));\ + nssct_set_index((_fdInf)->fd, (_proto));\ + +#define nstack_set_routed_fd(_fdInf, _protoFD) \ + (_fdInf)->rlfd = (_protoFD); \ + nsep_set_infoRlfd((_fdInf)->fd, (_protoFD));\ + + +nstack_fd_Inf *nstack_fd2inf (int fd); + +void nstack_reset_fdInf (nstack_fd_Inf * fdInf); + +static inline nstack_fd_Inf * +nstack_getValidInf (int fd) +{ + nstack_fd_Inf *retInf = NULL; + retInf = nstack_fd2inf (fd); + if (NULL == retInf || FD_OPEN != retInf->local_lock.fd_status) + { + return NULL; + } + return retInf; +} + +#define nstack_get_protoFd(fdInf, modInx) ((fdInf)->protoFD[modInx].fd) +#define nstack_set_bind_ret(fdInf, modInx, ret) ((fdInf)->protoFD[modInx].rslt.brslt = ret) +#define nstack_set_listen_ret(fdInf, modInx, ret) ((fdInf)->protoFD[modInx].rslt.lrslt = ret) +#define nstack_set_ret(fdInf, modInx, ret) ((fdInf)->protoFD[modInx].pad = ret) +#define nstack_set_listen_state(fdInf, modInx, state) ((fdInf)->protoFD[modInx].liststate = state) +#define nstack_get_listen_state(fdInf, modInx) ((fdInf)->protoFD[modInx].liststate) +#define nstack_get_listen_ret(fdInf, modInx) ((fdInf)->protoFD[modInx].rslt.lrslt) +#define nstack_get_bind_ret(fdInf, modInx) ((fdInf)->protoFD[modInx].rslt.brslt) +#define nstack_get_protoFdSt(fdInf, modInx) (&(fdInf)->protoFD[modInx]) +void nstack_set_protoFd (nstack_fd_Inf * fdInf, int modInx, int protofd); +void nstack_set_app_info (nstack_fd_Inf * fdInf, int modInx); + +int nstack_fd_free_with_kernel (nstack_fd_Inf * fdInf); +int nstack_fd_free_without_kernel (nstack_fd_Inf * fdInf, int ref); +extern nstack_fd_Inf *nstack_lk_fd_alloc_with_kernel (int nfd); //alloc a nstack socket that include kernel fd +extern void nstack_fd_free (nstack_fd_Inf * fdInf); + +void nstack_fork_init_child (pid_t ppid); +void nstack_fork_init_parent (pid_t ppid); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __NSTACK_FD_MNG_H__ */ diff --git a/src/nSocket/nstack/nstack_info_parse.c b/src/nSocket/nstack/nstack_info_parse.c new file mode 100644 index 0000000..06c956b --- /dev/null +++ b/src/nSocket/nstack/nstack_info_parse.c @@ -0,0 +1,493 @@ +/* +* +* 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 _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "json.h" +#include "nsfw_base_linux_api.h" +#include "nstack_info_parse.h" + +/*get string value*/ +#define NSTACK_JSON_PARSE_STRING(obj, name, lent, reslt, index) do { \ + struct json_object* temp_obj1 = NULL; \ + (void)json_object_object_get_ex((obj), (name), &temp_obj1); \ + if (temp_obj1) \ + { \ + const char *temp_value1 = json_object_get_string(temp_obj1); \ + if (!temp_value1) \ + { \ + NSSOC_LOGERR("can't get value from %s index:%d", name, (index)); \ + goto RETURN_ERROR; \ + } \ + (void)STRNCPY_S((reslt), (lent), temp_value1, (lent)); \ + } \ + else \ + { \ + NSSOC_LOGERR("can't get obj from %s index:%d", name, (index)); \ + goto RETURN_ERROR; \ + } \ +} while ( 0 ); + +/*get int value*/ +#define NSTACK_JSON_PARSE_INT(obj, name, lent, reslt, index) do { \ + struct json_object* temp_obj1 = NULL; \ + (void)json_object_object_get_ex((obj), (name), &temp_obj1); \ + if (temp_obj1) \ + { \ + const char *temp_value1 = json_object_get_string(temp_obj1); \ + if (!temp_value1) \ + { \ + NSSOC_LOGERR("can't get value from %s index:%d", name, (index)); \ + goto RETURN_ERROR; \ + } \ + (reslt) = atoi(temp_value1); \ + } \ + else \ + { \ + NSSOC_LOGERR("can't get obj from %s index:%d", name, (index)); \ + goto RETURN_ERROR; \ + } \ +} while ( 0 ); + +/*parse module cfg*/ +int +nstack_parse_module_cfg_json (char *param) +{ + struct json_object *obj = json_tokener_parse (param); + struct json_object *module_list_obj = NULL; + struct json_object *module_obj = NULL; + struct json_object *temp_obj = NULL; + const char *default_name = NULL; + const char *temp_value = NULL; + int module_num = 0; + int ret = NSTACK_RETURN_FAIL; + int index = 0; + int icnt = 0; + + if (!obj) + { + NSSOC_LOGERR ("json parse fail"); + return NSTACK_RETURN_FAIL; + } + + (void) MEMSET_S (&g_nstack_module_desc[0], sizeof (g_nstack_module_desc), 0, + sizeof (g_nstack_module_desc)); + + (void) json_object_object_get_ex (obj, "default_stack_name", &temp_obj); + if (!temp_obj) + { + NSSOC_LOGERR ("can't get module_list"); + goto RETURN_ERROR; + } + + default_name = json_object_get_string (temp_obj); + + (void) json_object_object_get_ex (obj, "module_list", &module_list_obj); + if (!module_list_obj) + { + NSSOC_LOGERR ("can't get module_list"); + goto RETURN_ERROR; + } + module_num = json_object_array_length (module_list_obj); + if ((module_num <= 0) || (module_num >= NSTACK_MAX_MODULE_NUM)) + { + NSSOC_LOGERR ("get module number:%d fail", module_num); + goto RETURN_ERROR; + } + + for (index = 0; index < module_num; index++) + { + module_obj = json_object_array_get_idx (module_list_obj, index); + if (module_obj) + { + NSTACK_JSON_PARSE_STRING (module_obj, "stack_name", MODULE_NAME_MAX, + &(g_nstack_module_desc[icnt].modName[0]), + index); + NSTACK_JSON_PARSE_STRING (module_obj, "function_name", + MODULE_NAME_MAX, + &(g_nstack_module_desc + [icnt].registe_fn_name[0]), index); + NSTACK_JSON_PARSE_STRING (module_obj, "libname", MODULE_NAME_MAX, + &(g_nstack_module_desc[icnt].libPath[0]), + index); + + (void) json_object_object_get_ex (module_obj, "loadtype", + &temp_obj); + if (temp_obj) + { + temp_value = json_object_get_string (temp_obj); + if (strcmp (temp_value, "static") == 0) + { + g_nstack_module_desc[icnt].libtype = NSTACK_LIB_LOAD_STATIC; + } + else + { + g_nstack_module_desc[icnt].libtype = NSTACK_LIB_LOAD_DYN; + } + } + else + { + NSSOC_LOGERR ("can't get value from loadtype index:%d", index); + goto RETURN_ERROR; + } + NSTACK_JSON_PARSE_INT (module_obj, "deploytype", MODULE_NAME_MAX, + g_nstack_module_desc[icnt].deploytype, + index); + NSTACK_JSON_PARSE_INT (module_obj, "maxfd", MODULE_NAME_MAX, + g_nstack_module_desc[icnt].maxfdid, index); + NSTACK_JSON_PARSE_INT (module_obj, "minfd", MODULE_NAME_MAX, + g_nstack_module_desc[icnt].minfdid, index); + NSTACK_JSON_PARSE_INT (module_obj, "priorty", MODULE_NAME_MAX, + g_nstack_module_desc[icnt].priority, index); + NSTACK_JSON_PARSE_INT (module_obj, "stackid", MODULE_NAME_MAX, + g_nstack_module_desc[icnt].modInx, index); + if (0 == strcmp (g_nstack_module_desc[icnt].modName, default_name)) + { + g_nstack_module_desc[icnt].default_stack = 1; + } + icnt++; + g_mudle_num = icnt; + } + } + ret = NSTACK_RETURN_OK; + +RETURN_ERROR: + json_object_put (obj); + return ret; +} + +/*parse module cfg*/ +int +nstack_parse_rd_cfg_json (char *param, rd_route_data ** data, int *num) +{ + struct json_object *obj = json_tokener_parse (param); + struct json_object *ip_list_obj = NULL; + struct json_object *proto_list_obj = NULL; + struct json_object *module_obj = NULL; + struct json_object *temp_obj = NULL; + rd_route_data *rdtemp = NULL; + rd_route_data *rddata = NULL; + const char *sub = NULL; + const char *temp_value = NULL; + int ip_list_num = 0; + int proto_list_num = 0; + int totalnum = 0; + int tlen = 0; + int index = 0; + int icnt = 0; + char ipadd[32] = { 0 }; + + if (!obj) + { + NSSOC_LOGERR ("json parse fail"); + return NSTACK_RETURN_FAIL; + } + + (void) json_object_object_get_ex (obj, "ip_route", &ip_list_obj); + if (!ip_list_obj) + { + NSSOC_LOGERR ("can't get module_list"); + goto RETURN_ERROR; + } + (void) json_object_object_get_ex (obj, "prot_route", &proto_list_obj); + if (!proto_list_obj) + { + NSSOC_LOGERR ("can't get module_list"); + goto RETURN_ERROR; + } + + ip_list_num = json_object_array_length (ip_list_obj); + proto_list_num = json_object_array_length (proto_list_obj); + totalnum = ip_list_num + proto_list_num; + if (totalnum > NSTACK_RD_MAX) + { + NSSOC_LOGERR ("rd num is too more, and return fail"); + goto RETURN_ERROR; + } + tlen = sizeof (rd_route_data) * totalnum; + rdtemp = (rd_route_data *) malloc (tlen); + if (!rdtemp) + { + NSSOC_LOGERR ("malloc mem fail"); + goto RETURN_ERROR; + } + MEMSET_S (rdtemp, tlen, 0, tlen); + for (index = 0; index < ip_list_num; index++) + { + module_obj = json_object_array_get_idx (ip_list_obj, index); + if (module_obj) + { + rddata = rdtemp + icnt; + rddata->type = RD_DATA_TYPE_IP; + (void) json_object_object_get_ex (module_obj, "type", &temp_obj); + if (temp_obj) + { + temp_value = json_object_get_string (temp_obj); + if (!temp_value) + { + NSSOC_LOGERR ("can't get value from subnet index:%d", + index); + goto RETURN_ERROR; + } + (void) STRNCPY_S (rddata->stack_name, RD_PLANE_NAMELEN, + temp_value, RD_PLANE_NAMELEN); + } + (void) json_object_object_get_ex (module_obj, "subnet", &temp_obj); + if (temp_obj) + { + temp_value = json_object_get_string (temp_obj); + if (!temp_value) + { + NSSOC_LOGERR ("can't get value from subnet index:%d", + index); + goto RETURN_ERROR; + } + sub = strstr (temp_value, "/"); + if (!sub) + { + NSSOC_LOGERR ("can't get maskklen from %s", temp_value); + goto RETURN_ERROR; + } + (void) MEMSET_S (ipadd, sizeof (ipadd), 0, sizeof (ipadd)); + (void) STRNCPY_S (ipadd, sizeof (ipadd), temp_value, + (size_t) (sub - temp_value)); + rddata->ipdata.masklen = atoi (sub + 1); + rddata->ipdata.addr = ntohl (inet_addr (ipadd)); + icnt++; + } + } + } + + for (index = 0; index < ip_list_num; index++) + { + module_obj = json_object_array_get_idx (proto_list_obj, index); + if (module_obj) + { + rddata = rdtemp + icnt; + rddata->type = RD_DATA_TYPE_PROTO; + (void) json_object_object_get_ex (module_obj, "type", &temp_obj); + if (temp_obj) + { + temp_value = json_object_get_string (temp_obj); + if (!temp_value) + { + NSSOC_LOGERR ("can't get value from subnet index:%d", + index); + goto RETURN_ERROR; + } + (void) STRNCPY_S (rddata->stack_name, RD_PLANE_NAMELEN, + temp_value, RD_PLANE_NAMELEN); + } + (void) json_object_object_get_ex (module_obj, "proto_type", + &temp_obj); + if (temp_obj) + { + temp_value = json_object_get_string (temp_obj); + if (!temp_value) + { + NSSOC_LOGERR ("can't get value from subnet index:%d", + index); + goto RETURN_ERROR; + } + rddata->proto_type = atoi (temp_value); + icnt++; + } + } + } + *data = rdtemp; + *num = icnt; + json_object_put (obj); + return NSTACK_RETURN_OK; +RETURN_ERROR: + json_object_put (obj); + if (rdtemp) + { + free (rdtemp); + } + return -1; +} + +/*read json file, and return a buf, if return success, the caller need to free **buf*/ +int +nstack_json_file_read (char *filename, char **buf) +{ + char *cfg_buf = NULL; + int fp = 0; + off_t file_len = 0; + off_t buff_len = 0; + int ret = NSTACK_RETURN_FAIL; + + if ((!filename) || (!buf)) + { + return NSTACK_RETURN_FAIL; + } + + fp = open (filename, O_RDONLY); + if (fp < 0) + { + NSSOC_LOGERR ("open %s fail, error:%d!", filename, errno); + ret = NSTACK_RETURN_FAIL; + goto RETURN_RELEASE; + } + + file_len = lseek (fp, 0, SEEK_END); + if (file_len <= 0) + { + NSSOC_LOGERR ("failed to get file len]file name=%s", filename); + ret = NSTACK_RETURN_FAIL; + goto RETURN_RELEASE; + } + + if (file_len > NSTACK_CFG_FILELEN_MAX) + { + NSSOC_LOGERR + ("file len is too big]file len=%d, max len=%d, file name=%s", + file_len, NSTACK_CFG_FILELEN_MAX, filename); + ret = NSTACK_RETURN_FAIL; + goto RETURN_RELEASE; + } + + ret = lseek (fp, 0, SEEK_SET); + if (ret < 0) + { + NSSOC_LOGERR ("seek to start failed]file name=%s", filename); + ret = NSTACK_RETURN_FAIL; + goto RETURN_RELEASE; + } + + buff_len = file_len + 1; + cfg_buf = (char *) malloc (buff_len); + if (!cfg_buf) + { + NSSOC_LOGERR ("malloc buff failed]buff_len=%d", buff_len); + ret = NSTACK_RETURN_FAIL; + goto RETURN_RELEASE; + } + + ret = MEMSET_S (cfg_buf, buff_len, 0, buff_len); + if (NSTACK_RETURN_OK != ret) + { + NSSOC_LOGERR ("MEMSET_S failed]ret=%d.", ret); + ret = NSTACK_RETURN_FAIL; + goto RETURN_RELEASE; + } + + ret = nsfw_base_read (fp, cfg_buf, buff_len - 1); + if (ret <= 0) + { + NSSOC_LOGERR ("read failed]ret=%d, errno:%d", ret, errno); + ret = NSTACK_RETURN_FAIL; + goto RETURN_RELEASE; + } + + *buf = cfg_buf; + nsfw_base_close (fp); + return NSTACK_RETURN_OK; +RETURN_RELEASE: + if (fp >= 0) + { + nsfw_base_close (fp); + } + if (cfg_buf) + { + free (cfg_buf); + } + return ret; +} + +/*parse module cfg file*/ +int +nstack_module_parse () +{ + char *modulecfg = NULL; + char *tmp_config_path = NULL; + char *cfg_buf = NULL; + int ret = NSTACK_RETURN_FAIL; + + modulecfg = getenv (NSTACK_MOD_CFG_FILE); + + if (modulecfg) + { + tmp_config_path = realpath (modulecfg, NULL); + } + else + { + tmp_config_path = realpath (DEFALT_MODULE_CFG_FILE, NULL); + } + + if (!tmp_config_path) + { + NSSOC_LOGERR ("nstack module file:%s get real path fail!", + modulecfg ? modulecfg : DEFALT_MODULE_CFG_FILE); + return NSTACK_RETURN_FAIL; + } + + ret = nstack_json_file_read (tmp_config_path, &cfg_buf); + if (NSTACK_RETURN_OK == ret) + { + ret = nstack_parse_module_cfg_json (cfg_buf); + free (cfg_buf); + } + + free (tmp_config_path); + return ret; +} + +int +nstack_stack_rd_parse (rd_route_data ** data, int *num) +{ + char *modulecfg = NULL; + char *tmp_config_path = NULL; + char *cfg_buf = NULL; + int ret = NSTACK_RETURN_FAIL; + + modulecfg = getenv (NSTACK_MOD_CFG_RD); + + if (modulecfg) + { + tmp_config_path = realpath (modulecfg, NULL); + } + else + { + tmp_config_path = realpath (DEFALT_RD_CFG_FILE, NULL); + } + + if (!tmp_config_path) + { + NSSOC_LOGERR ("nstack rd file:%s get real path fail!", + modulecfg ? modulecfg : DEFALT_MODULE_CFG_FILE); + return NSTACK_RETURN_FAIL; + } + + ret = nstack_json_file_read (tmp_config_path, &cfg_buf); + if (NSTACK_RETURN_OK == ret) + { + ret = nstack_parse_rd_cfg_json (cfg_buf, data, num); + free (cfg_buf); + } + + free (tmp_config_path); + return ret; +} diff --git a/src/nSocket/nstack/nstack_info_parse.h b/src/nSocket/nstack/nstack_info_parse.h new file mode 100644 index 0000000..0522d2c --- /dev/null +++ b/src/nSocket/nstack/nstack_info_parse.h @@ -0,0 +1,56 @@ +/* +* +* 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 _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#ifndef _NSTACK_INFO_PARSE_H_ +#define _NSTACK_INFO_PARSE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nstack_module.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nstack_rd.h" +#include "nstack_rd_data.h" + +#define DEFALT_MODULE_CFG_FILE "./module_config.json" +#define DEFALT_RD_CFG_FILE "./rd_config.json" +#define FILE_PATCH_MAX 256 +#define NSTACK_CFG_FILELEN_MAX (1 * 1024 * 1024) +#define NSTACK_RETURN_OK 0 +#define NSTACK_RETURN_FAIL -1 + +#define NSTACK_MOD_CFG_FILE "NSTACK_MOD_CFG_FILE" +#define NSTACK_MOD_CFG_RD "NSTACK_MOD_CFG_RD" + +extern nstack_module_keys g_nstack_module_desc[NSTACK_MAX_MODULE_NUM]; +extern ns_uint32 g_mudle_num; + +extern int nstack_module_parse (); +extern int nstack_stack_rd_parse (rd_route_data ** data, int *num); + +#endif diff --git a/src/nSocket/nstack/nstack_module.c b/src/nSocket/nstack/nstack_module.c new file mode 100644 index 0000000..17da42d --- /dev/null +++ b/src/nSocket/nstack/nstack_module.c @@ -0,0 +1,269 @@ +/* +* +* 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 _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nstack_module.h" +#include "common_mem_buf.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nstack_dmm_api.h" +#include "nstack_dmm_adpt.h" +#include "nstack_rd_init.h" +#include "nstack_info_parse.h" +#include "nstack_rd_mng.h" + +/* *INDENT-OFF* */ +nstack_module_info g_nstack_modules = { + .modNum = 0, + .fix_mid = -1, + .modules = {{{0}}}, + .defMod = NULL, + }; + +/* *INDENT-ON* */ +nstack_module_keys g_nstack_module_desc[NSTACK_MAX_MODULE_NUM]; + +ns_uint32 g_mudle_num = 0; + +int +nstack_get_deploy_type () +{ + int icnt = 0; + int type = 0; + for (icnt = 0; icnt < g_mudle_num; icnt++) + { + if (g_nstack_module_desc[icnt].deploytype > type) + { + type = g_nstack_module_desc[icnt].deploytype; + } + } + return type; +} + +NSTACK_STATIC inline int +nstack_register_one_module (nstack_module_keys * pKeys) +{ + + nstack_module *pmod = NULL; + nstack_stack_registe_fn stack_registe_fn = NULL; + nstack_event_cb val = { 0 }; + int retVal; + int ret = 0; + + if (pKeys->modInx >= NSTACK_MAX_MODULE_NUM) + { + NSSOC_LOGERR ("modeindex is overload]index=%d", pKeys->modInx); + ret = -1; + goto err_return; + } + + pmod = nstack_get_module (pKeys->modInx); + + retVal = + STRNCPY_S (pmod->modulename, NSTACK_PLUGIN_NAME_LEN, pKeys->modName, + NSTACK_PLUGIN_NAME_LEN); + if (EOK != retVal) + { + NSSOC_LOGERR ("STRNCPY_S failed]ret=%d", retVal); + ret = -1; + goto err_return; + } + + pmod->modulename[NSTACK_PLUGIN_NAME_LEN - 1] = '\0'; + pmod->priority = pKeys->priority; + pmod->modInx = pKeys->modInx; + pmod->maxfdid = pKeys->maxfdid; + pmod->minfdid = pKeys->minfdid; + pmod->ep_free_ref = pKeys->ep_free_ref; + + if (pKeys->libtype == NSTACK_LIB_LOAD_DYN) + { + pmod->handle = dlopen (pKeys->libPath, RTLD_LAZY); + if (!pmod->handle) + { + /*optimize dlopen err print */ + NSSOC_LOGERR ("dlopen lib=%s of module=%s failed, err_string=%s", + pKeys->libPath, pKeys->modName, dlerror ()); + ret = -1; + goto err_return; + } + } + else + { + pmod->handle = RTLD_DEFAULT; + } + + stack_registe_fn = dlsym (pmod->handle, pKeys->registe_fn_name); + if (!stack_registe_fn) + { + /* optimize dlopen err print */ + NSSOC_LOGERR ("registe function not found]err_string=%s", dlerror ()); + if (pmod->handle) + { + dlclose (pmod->handle); + pmod->handle = NULL; + } + ret = -1; + goto err_return; + } + val.handle = pmod->handle; + val.type = pKeys->modInx; + val.event_cb = nstack_event_callback; + if (stack_registe_fn (&pmod->mops, &val)) + { + NSSOC_LOGERR ("registe function failed"); + if (pmod->handle) + { + dlclose (pmod->handle); + pmod->handle = NULL; + } + ret = -1; + goto err_return; + } + + /* malloc length need protect + malloc parameter type is size_t */ + if (((pmod->maxfdid + 1) < 1) + || (SIZE_MAX / sizeof (ns_int32) < (pmod->maxfdid + 1))) + { + NSSOC_LOGERR ("malloc size is wrong]maxfdid=%d", pmod->maxfdid); + if (pmod->handle) + { + dlclose (pmod->handle); + pmod->handle = NULL; + } + ret = -1; + goto err_return; + } + +err_return: + return ret; +} + +/*nstack_register_module can't concurrent*/ +int +nstack_register_module () +{ + unsigned int idx = 0; + nstack_stack_info *pstacks = NULL; + int ret = 0; + + nstack_get_route_data rd_fun[] = { + nstack_stack_rd_parse, + nstack_rd_ip_get + }; + + pstacks = + (nstack_stack_info *) malloc (sizeof (nstack_stack_info) * g_mudle_num); + if (!pstacks) + { + NSSOC_LOGERR ("malloc failed]"); + return ns_fail; + } + ret = + MEMSET_S (pstacks, sizeof (nstack_stack_info) * g_mudle_num, 0, + sizeof (nstack_stack_info) * g_mudle_num); + if (EOK != ret) + { + NSSOC_LOGERR ("MEMSET_S failed]ret=%d", ret); + free (pstacks); + return ns_fail; + } + + for (idx = 0; idx < g_mudle_num; idx++) + { + if (0 != nstack_register_one_module (&g_nstack_module_desc[idx])) + { + NSSOC_LOGERR + ("can't register module]modInx=%d,modName=%s,libPath=%s", + g_nstack_module_desc[idx].modInx, + g_nstack_module_desc[idx].modName, + g_nstack_module_desc[idx].libPath); + free (pstacks); + return ns_fail; + } + ret = + STRCPY_S (pstacks[idx].name, STACK_NAME_MAX, + g_nstack_module_desc[idx].modName); + if (EOK != ret) + { + NSSOC_LOGERR ("STRCPY_S fail]idx=%d,modName=%s,ret=%d", idx, + g_nstack_module_desc[idx].modName, ret); + free (pstacks); + return ns_fail; + } + pstacks[idx].priority = g_nstack_module_desc[idx].priority; + pstacks[idx].stack_id = g_nstack_module_desc[idx].modInx; + if (g_nstack_module_desc[idx].default_stack == 1) + { + g_nstack_modules.defMod = + &g_nstack_modules.modules[g_nstack_module_desc[idx].modInx]; + g_nstack_modules.fix_mid = g_nstack_module_desc[idx].modInx; + } + } + + if (g_nstack_modules.fix_mid < 0) + { + free (pstacks); + NSSOC_LOGERR ("nstack fix mid is unknown and return fail"); + return ns_fail; + } + + g_nstack_modules.modNum = g_mudle_num; + /*rd module init */ + if (ns_success != + nstack_rd_init (pstacks, idx, rd_fun, + sizeof (rd_fun) / sizeof (nstack_get_route_data))) + { + free (pstacks); + NSSOC_LOGERR ("nstack rd init fail"); + return ns_fail; + } + free (pstacks); + return ns_success; +} + +int +nstack_stack_module_init () +{ + ns_uint32 idx; + for (idx = 0; idx < g_mudle_num; idx++) + { + if (g_nstack_modules.modules[idx].mops.extern_ops.module_init) + { + if (0 != + g_nstack_modules.modules[idx].mops.extern_ops.module_init ()) + { + NSSOC_LOGERR ("nstack[%s] modx:%d init fail", + g_nstack_modules.modules[idx].modulename, idx); + } + } + } + return 0; +} diff --git a/src/nSocket/nstack/nstack_module.h b/src/nSocket/nstack/nstack_module.h new file mode 100644 index 0000000..2aa5d3b --- /dev/null +++ b/src/nSocket/nstack/nstack_module.h @@ -0,0 +1,157 @@ +/* +* +* 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 __NSTACK_MODULE_H__ +#define __NSTACK_MODULE_H__ + +#include +#include +#include +#include "nstack_types.h" +#include "nstack_dmm_api.h" +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif + +#define NSTACK_LIB_LOAD_DYN 0 +#define NSTACK_LIB_LOAD_STATIC 1 + +#define NSTACK_PLUGIN_NAME_LEN 64 + +#define NSTACK_MAX_MODULE_NUM 8 +#define NSTACK_PRO_MODULE 1 + +#define MOD_INDEX_FOR_KERNEL 0 +#define MOD_NAME_FOR_KERNEL "kernel" +#define LIB_NAME_FOR_KERNEL "liblinuxkernel.so" +#define MAX_SOCK_FOR_KERNEL (MAX_SOCKET_NUM-1) + +#define MIN_SOCK_FOR_KERNEL 0 + +#define LIB_NAME_FOR_STACKX "libnstack.so" +#define MAX_SOCK_FOR_STACKX MAX_SOCKET_NUM + +#define MIN_SOCK_FOR_STACKX 0 + +#define MOD_PRI_FOR_STACKX 1 +#define REG_FUN_FOR_STACKX "nstack_stack_register" + +#define NSTACK_EP_FREE_NEED_REF 1 /*when epoll information free, need to wait that stack would not notify event */ +#define NSTACK_EP_FREE_NONEED_REF 0 + +#define MODULE_NAME_MAX 64 + +typedef struct __NSTACK_MODULE_KEYS +{ + ns_char modName[MODULE_NAME_MAX]; /*stack name */ + ns_char registe_fn_name[MODULE_NAME_MAX]; /*stack regist fun name */ + ns_char libPath[MODULE_NAME_MAX]; /*if libtype is dynamic, it is the path of lib */ + ns_char deploytype; /*delpoly model type: model type1, model type2, model type3 */ + ns_char libtype; /*dynamic lib or static lib */ + ns_char ep_free_ref; /*when epoll information free, + *need to wait that stack would not notify event + */ + ns_char default_stack; /*whether is default stack:when don't know how to choose stack, + *just use default stack + */ + ns_int32 priority; + ns_int32 maxfdid; //the max fd id + ns_int32 minfdid; //the min fd id + ns_int32 modInx; // This is alloced by nStack , not from configuration +} nstack_module_keys; + +typedef struct __NSTACK_MODULE +{ + char modulename[NSTACK_PLUGIN_NAME_LEN]; + ns_int32 priority; + void *handle; + nstack_proc_cb mops; + ns_int32 ep_free_ref; //ep information need free with ref + ns_int32 modInx; // The index of module + ns_int32 maxfdid; //the max fd id + ns_int32 minfdid; //the min fd id +} nstack_module; + +typedef struct +{ + ns_int32 modNum; // Number of modules registed + ns_int32 fix_mid; + nstack_module *defMod; // The default module + nstack_module modules[NSTACK_MAX_MODULE_NUM]; +} nstack_module_info; + +/*register module according the modulecfg file*/ +extern ns_int nstack_register_module (); + +/***************************************************************** +Parameters : ops never be null; nstack api calls it; +Return : 0,not match; 1, match +Description : +*****************************************************************/ +extern nstack_module_info g_nstack_modules; +extern nstack_module_keys g_nstack_module_desc[]; + +#define nstack_defmod_name() (g_nstack_modules.defMod->modulename) +#define nstack_default_module() (g_nstack_modules.defMod) +#define nstack_defMod_inx() (g_nstack_modules.defMod->modInx) +#define nstack_get_module(inx) (&g_nstack_modules.modules[(inx)]) +#define nstack_get_modNum() (g_nstack_modules.modNum) +#define nstack_get_module_name_by_idx(inx) (g_nstack_modules.modules[inx].modulename) +#define nstack_def_ops() (&g_nstack_modules.defMod->mops.socket_ops) +#define nstack_module_ops(modInx) (&g_nstack_modules.modules[(modInx)].mops.socket_ops) + +#define nstack_get_maxfd_id(modInx) (g_nstack_modules.modules[modInx].maxfdid) +#define nstack_get_minfd_id(modInx) (g_nstack_modules.modules[modInx].minfdid) +#define nstack_get_descmaxfd_id(modInx) (g_nstack_module_desc[modInx].maxfdid) +#define nstack_epinfo_free_flag(modInx) (g_nstack_modules.modules[(modInx)].ep_free_ref == NSTACK_EP_FREE_NEED_REF) + +#define nstack_extern_deal(modInx) (g_nstack_modules.modules[(modInx)].mops.extern_ops) + +#define nstack_defMod_profd(fdInf) ((fdInf)->protoFD[g_nstack_modules.defMod->modInx].fd) +#define nstack_inf_modProfd(fdInf, pMod) ((fdInf)->protoFD[(pMod)->modInx].fd) + +#define nstack_get_fix_mid() (g_nstack_modules.fix_mid) +#define nstack_fix_mid_ops() (&(g_nstack_modules.modules[g_nstack_modules.fix_mid].mops.socket_ops)) +#define nstack_fix_stack_name() (g_nstack_modules.modules[g_nstack_modules.fix_mid].modulename) + +#define nstack_fix_fd_check() ((g_nstack_modules.fix_mid >= 0) && (g_nstack_modules.fix_mid < NSTACK_MAX_MODULE_NUM) \ + ? g_nstack_modules.modules[g_nstack_modules.fix_mid].mops.extern_ops.stack_fd_check \ + : NULL) + +#define nstack_each_modOps(modInx, ops) \ + for ((modInx) = 0; ((modInx) < nstack_get_modNum() && ((ops) = nstack_module_ops(modInx))); (modInx)++) + +#define nstack_each_modInx(modInx) \ + for ((modInx) = 0; ((modInx) < nstack_get_modNum()); (modInx)++) + +#define nstack_each_module(modInx, pMod) \ + for ((modInx) = 0; ((modInx) < nstack_get_modNum() && (pMod = nstack_get_module((modInx)))); (modInx)++) + +int nstack_stack_module_init (); + +int nstack_get_deploy_type (); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __NSTACK_MODULE_H__ */ diff --git a/src/nSocket/nstack/nstack_nsocket_construct.c b/src/nSocket/nstack/nstack_nsocket_construct.c new file mode 100644 index 0000000..31f2b55 --- /dev/null +++ b/src/nSocket/nstack/nstack_nsocket_construct.c @@ -0,0 +1,43 @@ +/* +* +* 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 "nsfw_init.h" +#include "nsfw_mem_api.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_recycle_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSACK_NSOCKET_MODULE "nSocket" + +extern int nstack_app_init (void *ppara); +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSACK_NSOCKET_MODULE) +NSFW_MODULE_PRIORITY (7) +NSFW_MODULE_DEPENDS (NSFW_MGR_COM_MODULE) +NSFW_MODULE_DEPENDS (NSFW_MEM_MGR_MODULE) +NSFW_MODULE_DEPENDS (NSFW_RECYCLE_MODULE) +NSFW_MODULE_INIT (nstack_app_init) +/* *INDENT-ON* */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ \ No newline at end of file diff --git a/src/nSocket/nstack/nstack_socket.c b/src/nSocket/nstack/nstack_socket.c new file mode 100644 index 0000000..d27d70d --- /dev/null +++ b/src/nSocket/nstack/nstack_socket.c @@ -0,0 +1,2816 @@ +/* +* +* 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 +#include + +#ifndef __USE_GNU +#define __USE_GNU +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* define RTLD_NEXT */ +#endif + +#include +#include +#include +#include "nstack.h" +#include "nstack_socket.h" +#include "nstack_fd_mng.h" +#include "nstack_dmm_api.h" +#include "nstack_sockops.h" +#include "nstack_module.h" +#include "common_mem_spinlock.h" +#include "nstack_securec.h" +#include "nsfw_init.h" +#include "nsfw_recycle_api.h" +#include "nsfw_base_linux_api.h" +#include "nstack_rd_data.h" +#include "nstack_rd.h" +#include "select_adapt.h" +#include "nstack_select.h" +#include "nstack_share_res.h" +#include "nstack_trace.h" +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +#define NSTACK_LOOP_IP 0x100007f +#define NSTACK_ANY_IP 0x0 + +#ifndef REPLAYS_POSIX_API +#define REPLAYS_POSIX_API 1 +#endif + +#if REPLAYS_POSIX_API +#define strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +#undef NSTACK_MK_DECL +#define NSTACK_MK_DECL(ret, fn, args) strong_alias(nstack_##fn, fn) +#include +#endif + +#define NSTACK_FUN_CHECK_RET(fdops, mod, fun) \ + if (!(fdops) || !(fdops)->pf##fun) \ + { \ + nstack_set_errno(ENOSYS); \ + NSSOC_LOGERR("nstack module:%d ops:%p, ops->pf%s:%p error [return]", mod, fdops, #fun, (fdops)->pf##fun); \ + return -1; \ + } + +#define NSTACK_DOMAIN_CHEKRET(domainVal, fn, para) { \ + if ((domainVal != AF_INET) \ + && (domainVal != PF_INET)) \ + { \ + int _ret_ = 0; \ + if (nstack_fix_fd_check() && nstack_fix_fd_check()(-1, STACK_FD_FUNCALL_CHECK)) \ + { \ + NSTACK_CAL_FUN(nstack_fix_mid_ops(), fn, para, _ret_); \ + } \ + return _ret_; \ + } \ +} + +#define NSTACK_FD_LINUX_CHECK(fdVal, fn, fdInf, para) { \ + if (!(fdInf = nstack_getValidInf(fdVal))) \ + { \ + if (NSTACK_THREAD_LOADING()) \ + { \ + return nsfw_base_##fn para;\ + } \ + if (0 == nstack_stack_module_load()) \ + { \ + if (nstack_fix_fd_check() && nstack_fix_fd_check()(fdVal, STACK_FD_FUNCALL_CHECK)) \ + { \ + int _ret_ = 0; \ + NSTACK_CAL_FUN(nstack_fix_mid_ops(), fn, para, _ret_); \ + return _ret_; \ + } \ + } \ + nstack_set_errno(ENOSYS); \ + return -1; \ + } \ +} + +#define NSTACK_SELECT_LINUX_CHECK() (get_select_module()->inited) + +/* Supports multi-threaded and multi-process */ +NSTACK_STATIC inline void +set_fd_status (int fd, FD_STATUS status) +{ + nstack_fd_local_lock_info_t *local_lock = get_fd_local_lock_info (fd); + if (local_lock) + { + if (FD_OPEN == status) + { + atomic_inc (&local_lock->fd_ref); + } + local_lock->fd_status = status; + } +} + +void +set_fd_status_lock_fork (int fd, FD_STATUS status) +{ + common_mem_rwlock_read_lock (get_fork_lock ()); + set_fd_status (fd, status); + common_mem_rwlock_read_unlock (get_fork_lock ()); +} + +/***************************************************************** +Parameters : domain + type + protocol +Return : +Description : create a nstack fd for application +*****************************************************************/ +int +nstack_socket (int domain, int itype, int protocol) +{ + int ret = -1; //tmp ret of a Single proctol mode. + int rdret = -1; //the final Return judge vale. + int modInx; + nstack_socket_ops *ops; + int ret_fd = -1; + int protoFD[NSTACK_MAX_MODULE_NUM]; + nstack_rd_key rdkey = { 0 }; + int selectmod = -1; + + nstack_set_tracing_contex (0, 0, -1); + + /*check whether module init finish or not */ + NSTACK_INIT_CHECK_RET (socket); + + NSSOC_LOGINF ("(domain=%d, type=%d, protocol=%d) [Caller]", domain, itype, + protocol); + + /*if domain don't equal AF_INET , just call linux */ + NSTACK_DOMAIN_CHEKRET (domain, socket, (domain, itype, protocol)); + + nstack_each_modInx (modInx) + { + protoFD[modInx] = -1; + } + + /*create the fix socket first, and check it wether ok */ + NSTACK_CAL_FUN (nstack_fix_mid_ops (), socket, (domain, itype, protocol), + ret_fd); + if (!nstack_is_nstack_sk (ret_fd)) + { + if (ret_fd >= 0) + { + NSTACK_CAL_FUN (nstack_fix_mid_ops (), close, (ret_fd), ret); + nstack_set_errno (EMFILE); + } + NSSOC_LOGERR + ("[nstack_linux]domain=%d,type=%d protocol=%d linux fd=%d is too big and return fail [return]", + domain, itype, protocol, ret_fd); + return ns_fail; + } + + protoFD[nstack_get_fix_mid ()] = ret_fd; + + nstack_fd_local_lock_info_t *lock_info = get_fd_local_lock_info (ret_fd); + LOCK_FOR_EP (lock_info); + + /*check wether select stack create success, if no return fail */ + rdkey.type = RD_DATA_TYPE_PROTO; + rdkey.proto_type = itype; + rdret = nstack_rd_get_stackid (&rdkey, &selectmod); + if ((0 != rdret) || (selectmod < 0) || (selectmod >= nstack_get_modNum ())) + { + NSSOC_LOGERR ("protocol:%d select stack fail", protocol); + selectmod = -1; + } + else + { + NSSOC_LOGINF ("Create socket of]select modName=%s", + nstack_get_module_name_by_idx (selectmod)); + } + + /*create socket by calling select module or all module */ + nstack_each_modOps (modInx, ops) + { + if (modInx == nstack_get_fix_mid ()) + { + continue; + } + /*if no module selected then create all or just create selected stack */ + if ((selectmod == -1) || (modInx == selectmod)) + { + NSTACK_CAL_FUN (ops, socket, (domain, itype, protocol), ret); + protoFD[modInx] = ret; + NSSOC_LOGINF ("Create socket of]modName=%s:%d", + nstack_get_module_name_by_idx (modInx), + protoFD[modInx]); + if ((modInx == selectmod) && (-1 == ret)) + { + goto SOCKET_ERR; + } + } + } + + /* alloc nstack fd info */ + nstack_fd_Inf *fdInf = nstack_lk_fd_alloc_with_kernel (ret_fd); + if (NULL == fdInf) + { + /*if alloc failed */ + nstack_set_errno (EMFILE); + NSSOC_LOGERR ("have no available nstack_fd_Inf [return]"); + goto SOCKET_ERR; + } + + /*save the fd into fdinfo */ + fdInf->type = itype; + nstack_each_modInx (modInx) + { + if (-1 != protoFD[modInx]) + { + nstack_set_ret (fdInf, modInx, 0); + nstack_set_protoFd (fdInf, modInx, protoFD[modInx]); + nstack_set_app_info (fdInf, modInx); + } + } + set_fd_status_lock_fork (ret_fd, FD_OPEN); + + /*if some stack was choose, just set the chose stack */ + if (-1 != selectmod) + { + fdInf->ops = nstack_module_ops (selectmod); + nstack_set_router_protocol (fdInf, selectmod); + nstack_set_routed_fd (fdInf, protoFD[selectmod]); + } + NSSOC_LOGINF ("create fix stack[%s] fd=%d,fdInf->fd=%d,ret=%d [return]", + nstack_fix_stack_name (), ret_fd, fdInf->fd, ret_fd); + UNLOCK_FOR_EP (lock_info); + return ret_fd; + +SOCKET_ERR: + nstack_each_modOps (modInx, ops) + { + if (-1 != protoFD[modInx]) + { + NSTACK_CAL_FUN (ops, close, (protoFD[modInx]), ret); + } + } + UNLOCK_FOR_EP (lock_info); + return -1; +} + +/***************************************************************** +Parameters : fd + addr + len +Return : +Description : the code of bind&listen are same, if there are another same api we should extract +*****************************************************************/ +int +nstack_bind (int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + nstack_fd_Inf *fdInf; + int retval = ns_fail; + int tem = -1; + int modIdx = 0; + int tfd; + int selectmod = -1; + struct sockaddr_in *iaddr = NULL; + nstack_rd_key rdkey = { 0 }; + + nstack_set_tracing_contex (0, 0, fd); + + NSSOC_LOGINF ("(sockfd=%d, addr=%p, addrlen=%u) [Caller]", fd, addr, + addrlen); + + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("invalid input]fd=%d,addr=%p,len=0x%x [return]", fd, addr, + addrlen); + return -1; + } + if ((NULL == addr) || (addrlen < 2)) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR ("invalid input]fd=%d,addr=%p,len=0x%x [return]", fd, addr, + addrlen); + return -1; + } + iaddr = (struct sockaddr_in *) addr; + + if ((addrlen >= sizeof (struct sockaddr_in)) + && ((addr->sa_family) == AF_INET)) + { + NSSOC_LOGINF ("fd=%d,addr=%s,port=%d", fd, inet_ntoa (iaddr->sin_addr), + ntohs (iaddr->sin_port)); + } + else + { + NSSOC_LOGINF ("addrlen = %d ,fd=%d", (int) addrlen, fd); + } + + NSTACK_FD_LINUX_CHECK (fd, bind, fdInf, (fd, addr, addrlen)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_COMMON (fd, fdInf, local_lock); + + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_COMMON (fd, bind, fdInf, ENOTSOCK, + local_lock); + + /*bind repeat, first time success, other return fail */ + if (fdInf->isBound) + { + nstack_set_errno (EINVAL); + NSPOL_LOGERR ("error, alread bind]fd=%d", fd); + UNLOCK_COMMON (fd, local_lock); + return -1; + } + + /*just support af_inet and pf_inet */ + if (iaddr->sin_family != AF_INET && iaddr->sin_family != PF_INET) + { + nstack_set_errno (EAFNOSUPPORT); + NSSOC_LOGERR ("not surport]fd=%d,domain=%d,[return]", fd, + iaddr->sin_family); + UNLOCK_COMMON (fd, local_lock); + return -1; + } + + /* need check addrlen's validity, will visite iaddr->sin_addr.s_addr following code + for visite iaddr->sin_addr.s_addr is 8 byte */ + if (addrlen < 8) + { + nstack_set_errno (EINVAL); + NSPOL_LOGERR ("addrlenops) + { + NSTACK_CAL_FUN (fdInf->ops, bind, (fdInf->rlfd, addr, addrlen), tem); + if (ns_success == tem) + { + retval = ns_success; + nstack_set_bind_ret (fdInf, fdInf->rmidx, NSTACK_BIND_SUCCESS); + } + else + { + nstack_set_bind_ret (fdInf, fdInf->rmidx, NSTACK_BIND_FAIL); + } + goto bind_over; + } + + /*loop ip call linux */ + rdkey.type = RD_DATA_TYPE_IP; + rdkey.ip_addr = iaddr->sin_addr.s_addr; + retval = nstack_rd_get_stackid (&rdkey, &selectmod); + if ((ns_success != retval) && (-1 != selectmod)) + { + NSSOC_LOGWAR ("fd Can't select any module for]fd=%d,IP==%s", fd, + inet_ntoa ((iaddr->sin_addr))); + selectmod = -1; + } + else + { + NSSOC_LOGINF ("fd addr Select module]fd=%d,addr=%s,module=%s", + fd, inet_ntoa (iaddr->sin_addr), + nstack_get_module_name_by_idx (selectmod)); + } + + retval = -1; + nstack_each_modInx (modIdx) + { + tfd = nstack_get_protoFd (fdInf, modIdx); + if ((-1 == tfd) || (selectmod != modIdx)) // for INADDR_ANY, need try to bind on both stack-x and linux + { + /*tfd is -1, but is the select module */ + if (selectmod == modIdx) + { + retval = -1; + nstack_set_errno (ENOSYS); + NSSOC_LOGDBG + ("fd tfd=-1, but is the select module]fd=%d,tfd=-1,modIdx=%d", + fd, modIdx); + } + nstack_set_bind_ret (fdInf, modIdx, NSTACK_BIND_FAIL); + continue; + } + + NSTACK_CAL_FUN (nstack_module_ops (modIdx), bind, (tfd, addr, addrlen), + tem); + + if (ns_success == tem) + { + fdInf->ops = nstack_module_ops (modIdx); + nstack_set_router_protocol (fdInf, modIdx); + nstack_set_routed_fd (fdInf, tfd); + retval = ns_success; + nstack_set_bind_ret (fdInf, modIdx, NSTACK_BIND_SUCCESS); + } + else + { + NSSOC_LOGWAR ("bind fail]module=%s,fd=%d", + nstack_get_module_name_by_idx (modIdx), tfd); + nstack_set_bind_ret (fdInf, modIdx, NSTACK_BIND_FAIL); + } + } + + if (-1 == selectmod) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR ("failed for no module selected]fd=%d", fd); + } + +bind_over: + if (ns_success == retval) + { + fdInf->isBound = 1; + } + NSSOC_LOGINF ("appfd=%d,prot_fd=%d,rmidx=%d, retVal=%d [return]", fd, + fdInf->rlfd, fdInf->rmidx, retval); + UNLOCK_COMMON (fd, local_lock); + return retval; +} + +int +nstack_listen (int fd, int backlog) +{ + nstack_fd_Inf *fdInf; + int retval = -1; + int tem = -1; + int modIdx = 0; + int tfd; + int func_called = 0; + + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGINF ("(sockfd=%d, backlog=%d) [Caller]", fd, backlog); + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("invalid input]fd=%d,backlog=%d [return]", fd, backlog); + return -1; + } + + NSTACK_FD_LINUX_CHECK (fd, listen, fdInf, (fd, backlog)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_COMMON (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_COMMON (fd, listen, fdInf, ENOTSOCK, + local_lock); + + /*listen:use all mode we support */ + nstack_each_modInx (modIdx) + { + tfd = nstack_get_protoFd (fdInf, modIdx); + + if ((-1 == tfd) + || (NSTACK_BIND_FAIL == nstack_get_bind_ret (fdInf, modIdx))) + { + continue; + } + + func_called = 1; + NSTACK_CAL_FUN (nstack_module_ops (modIdx), listen, (tfd, backlog), tem); + if (ns_success == tem) + { + nstack_set_listen_state (fdInf, modIdx, NSTACK_LISENING); + NSTACK_SET_FD_LISTEN_SOCKET (fdInf); + retval = ns_success; + nstack_set_listen_ret (fdInf, modIdx, NSTACK_LISTEN_SUCCESS); + } + else + { + NSSOC_LOGWAR ("listen fail]fd=%d,module=%s,tfd=%d", fd, + nstack_get_module_name_by_idx (modIdx), tfd); + nstack_set_listen_ret (fdInf, modIdx, NSTACK_LISTEN_FAIL); + nstack_set_listen_state (fdInf, modIdx, NSTACK_NO_LISENING); + } + } + + if (0 == func_called) + { + retval = -1; + nstack_set_errno (ENOSYS); + NSSOC_LOGERR ("listen fail for no module called]fd=%d", fd); + } + + NSSOC_LOGINF ("fd=%d,ret=%d [return]", fd, retval); + UNLOCK_COMMON (fd, local_lock); + return retval; +} + +int +nstack_accept (int fd, struct sockaddr *addr, socklen_t * addr_len) +{ + nstack_fd_Inf *apstfdInf = NULL; + int tfd = -1; + int accfd = -1; + int fix_fd; + int ret_fd = -1; + nstack_fd_Inf *accInf; + int ret = -1; + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGINF ("(sockfd=%d, addr=%p, addrlen=%p) [Caller]", fd, addr, + addr_len); + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("fd is invalid]fd=%d [return]", fd); + return -1; + } + NSTACK_FD_LINUX_CHECK (fd, accept, apstfdInf, (fd, addr, addr_len)); + + nstack_fd_local_lock_info_t *local_lock = &apstfdInf->local_lock; + LOCK_ACCEPT (fd, apstfdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_ACCEPT (fd, accept, apstfdInf, ENOTSOCK, + local_lock); + + if (addr) + { + if ((!addr_len) || (*addr_len == NSTACK_MAX_U32_NUM)) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR ("addr_len inpurt error [return]"); + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + } + + /*if no module select or listen / bind fail, just return fail */ + if ((!apstfdInf->ops) + || (NSTACK_LISTEN_FAIL == + nstack_get_listen_ret (apstfdInf, apstfdInf->rmidx)) + || (NSTACK_BIND_FAIL == + nstack_get_bind_ret (apstfdInf, apstfdInf->rmidx))) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR + ("nstack accept fd=%d no mudle select, or bind/listen fail [return]", + fd); + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + tfd = nstack_get_protoFd (apstfdInf, apstfdInf->rmidx); + NSTACK_CAL_FUN (nstack_module_ops (apstfdInf->rmidx), accept, + (tfd, addr, addr_len), accfd); + NSSOC_LOGINF ("nstack fd=%d:%d accept fd=%d from module=%s", fd, tfd, accfd, + nstack_get_module_name_by_idx (apstfdInf->rmidx)); + if (-1 == accfd) + { + if (errno != EAGAIN) + { + NSSOC_LOGERR ("appfd=%d,module=%s,ret=%d,errno=%d [return]", fd, + nstack_get_module_name_by_idx (apstfdInf->rmidx), + accfd, errno); + } + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + + // If it is not from kernel, need to create one kernel socket + if (apstfdInf->rmidx != nstack_get_fix_mid ()) + { + /*err num is same with linux */ + fix_fd = nstack_extern_deal (nstack_get_fix_mid ()).stack_alloc_fd (); + if (fix_fd < 0) + { + NSSOC_LOGERR + ("nstack accept fd=%d return fd=%d kernelFD fd create fail [return]", + fd, accfd); + NSTACK_CAL_FUN (nstack_module_ops (apstfdInf->rmidx), close, + (accfd), ret); + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + } + else + { + fix_fd = accfd; + } + + if (fix_fd >= (int) NSTACK_KERNEL_FD_MAX) + { + /* nstack not support kernel fd >= NSTACK_MAX_SOCK_NUM. + * close it and nstack_accept() return failed + */ + NSSOC_LOGERR ("kernelFD fd too big, close it. kernelFD=%d [return]", + accfd); + NSTACK_CAL_FUN (nstack_module_ops (apstfdInf->rmidx), close, (accfd), + ret); + if (apstfdInf->rmidx != nstack_get_fix_mid ()) + { + NSTACK_CAL_FUN (nstack_fix_mid_ops (), close, (fix_fd), ret); + } + nstack_set_errno (EMFILE); + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + + nstack_fd_local_lock_info_t *lock_info = get_fd_local_lock_info (fix_fd); + LOCK_FOR_EP (lock_info); + + accInf = nstack_lk_fd_alloc_with_kernel (fix_fd); + ret_fd = fix_fd; + + if (NULL == accInf) + { + NSSOC_LOGERR ("Can't alloc nstack fdInf [return]"); + NSTACK_CAL_FUN (nstack_module_ops (apstfdInf->rmidx), close, (accfd), + ret); + if (apstfdInf->rmidx != nstack_get_fix_mid ()) + { + NSTACK_CAL_FUN (nstack_fix_mid_ops (), close, (fix_fd), ret); + } + UNLOCK_FOR_EP (lock_info); + nstack_set_errno (EMFILE); + UNLOCK_ACCEPT (fd, local_lock); + + return -1; + } + + nstack_set_routed_fd (accInf, accfd); + accInf->ops = nstack_module_ops (apstfdInf->rmidx); + /*donot include SOCK_CLOEXEC SOCK_NONBLOCK */ + accInf->type = + apstfdInf->type & (~((ns_int32) SOCK_CLOEXEC | (ns_int32) SOCK_NONBLOCK)); + nstack_set_router_protocol (accInf, apstfdInf->rmidx); + nstack_set_protoFd (accInf, apstfdInf->rmidx, accfd); + nstack_set_app_info (accInf, apstfdInf->rmidx); + /* Set the linux kernel fd also in accInf for kernel module (0) */ + if (apstfdInf->rmidx != nstack_get_fix_mid ()) + { + nstack_set_protoFd (accInf, nstack_get_fix_mid (), fix_fd); + } + NSSOC_LOGINF ("listenfd=%d,acceptfd=%d,module=%s(rlfd=%d),ret=%d [return]", + fd, ret_fd, nstack_get_module_name_by_idx (apstfdInf->rmidx), + accfd, ret_fd); + + set_fd_status_lock_fork (ret_fd, FD_OPEN); + UNLOCK_FOR_EP (lock_info); + UNLOCK_ACCEPT (fd, local_lock); + return ret_fd; +} + +int +nstack_accept4 (int fd, struct sockaddr *addr, + socklen_t * addr_len, int flags) +{ + nstack_fd_Inf *pstfdInf = NULL; + int tfd = -1; + int accfd = -1; + int fix_fd = -1; + int ret_fd = -1; + int ret = -1; + nstack_fd_Inf *accInf; + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGINF ("(sockfd=%d, addr=%p, addrlen=%p, flags=%d) [Caller]", fd, + addr, addr_len, flags); + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("nstack accept4,fd=%d invalid [return]", fd); + return -1; + } + NSTACK_FD_LINUX_CHECK (fd, accept4, pstfdInf, (fd, addr, addr_len, flags)); + + nstack_fd_local_lock_info_t *local_lock = &pstfdInf->local_lock; + LOCK_ACCEPT (fd, pstfdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_ACCEPT (fd, accept4, pstfdInf, ENOTSOCK, + local_lock); + + if (addr) + { + if ((!addr_len) || (*addr_len == NSTACK_MAX_U32_NUM)) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR ("nstack accept4 addr_len inpurt error [return]"); + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + } + + /*if no module select or listen / bind fail, just return fail */ + if ((!pstfdInf->ops) + || (NSTACK_LISTEN_FAIL == + nstack_get_listen_ret (pstfdInf, pstfdInf->rmidx)) + || (NSTACK_BIND_FAIL == + nstack_get_bind_ret (pstfdInf, pstfdInf->rmidx))) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR + ("nstack accept4 fd:%d no mudle select, or bind/listen fail [return]", + fd); + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + + tfd = nstack_get_protoFd (pstfdInf, pstfdInf->rmidx); + NSTACK_CAL_FUN (nstack_module_ops (pstfdInf->rmidx), accept4, + (tfd, addr, addr_len, flags), accfd); + if (-1 == accfd) + { + if (errno != EAGAIN) + { + NSSOC_LOGERR ("appfd=%d,module=%s,ret=%d,errno=%d [return]", fd, + nstack_get_module_name_by_idx (pstfdInf->rmidx), + accfd, errno); + } + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + + // If it is not from kernel, need to create one kernel socket + if (pstfdInf->rmidx != nstack_get_fix_mid ()) + { + fix_fd = nstack_extern_deal (nstack_get_fix_mid ()).stack_alloc_fd (); + } + else + { + fix_fd = accfd; + } + + if (!nstack_is_nstack_sk (fix_fd)) + { + /* nstack not support kernel fd >= NSTACK_MAX_SOCK_NUM. + * close it and nstack_accept() return failed + */ + NSSOC_LOGERR + ("nstack accept4 fd=%d kernelFD fd too big, close it. kernelFD=%d [return]", + fd, fix_fd); + if (fix_fd >= 0) + { + NSTACK_CAL_FUN (nstack_module_ops (pstfdInf->rmidx), close, (accfd), + ret); + } + + if (pstfdInf->rmidx != nstack_get_fix_mid ()) + { + NSTACK_CAL_FUN (nstack_module_ops (nstack_get_fix_mid ()), close, + (fix_fd), ret); + } + nstack_set_errno (EMFILE); + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + + nstack_fd_local_lock_info_t *lock_info = get_fd_local_lock_info (fix_fd); + LOCK_FOR_EP (lock_info); + accInf = nstack_lk_fd_alloc_with_kernel (fix_fd); + ret_fd = fix_fd; + + if (NULL == accInf) + { + NSTACK_CAL_FUN (nstack_module_ops (pstfdInf->rmidx), close, (accfd), + ret); + if (pstfdInf->rmidx != nstack_get_fix_mid ()) + { + NSTACK_CAL_FUN (nstack_module_ops (nstack_get_fix_mid ()), close, + (fix_fd), ret); + } + UNLOCK_FOR_EP (lock_info); + NSSOC_LOGERR ("nstack accept fd alloc is NULL [return]"); + UNLOCK_ACCEPT (fd, local_lock); + return -1; + } + + nstack_set_routed_fd (accInf, accfd); + accInf->ops = nstack_module_ops (pstfdInf->rmidx); + accInf->type = + (pstfdInf->type & (~((ns_int32) SOCK_CLOEXEC | (ns_int32) SOCK_NONBLOCK))) + | (ns_int32) flags; + nstack_set_router_protocol (accInf, pstfdInf->rmidx); + nstack_set_protoFd (accInf, pstfdInf->rmidx, accfd); + nstack_set_app_info (accInf, pstfdInf->rmidx); + /* Set the linux kernel fd also in accInf for kernel module (0) */ + if (pstfdInf->rmidx != nstack_get_fix_mid ()) + { + nstack_set_protoFd (accInf, nstack_get_fix_mid (), fix_fd); + } + NSSOC_LOGINF + ("listenfd=%d,acceptfd=%d,accInf->fd=%d,module=%s(rlfd:%d),ret=%d [return]", + fd, ret_fd, accInf->fd, nstack_get_module_name_by_idx (pstfdInf->rmidx), + accfd, ret_fd); + set_fd_status_lock_fork (ret_fd, FD_OPEN); + UNLOCK_FOR_EP (lock_info); + UNLOCK_ACCEPT (fd, local_lock); + return ret_fd; +} + +/***************************************************************** +Parameters : fd + addr + len +Return : +Description : use the rd select rlfd or default rlfd to Estblsh connection. the unused fd should closed +*****************************************************************/ +int +nstack_connect (int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + int retval = -1; + nstack_fd_Inf *fdInf; + struct sockaddr_in *iaddr = NULL; + iaddr = (struct sockaddr_in *) addr; + int selectmod = -1; + nstack_rd_key rdkey = { 0 }; + + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGINF ("(sockfd=%d, addr=%p, addrlen=%u) [Caller]", fd, addr, + addrlen); + + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR + ("nstack connect, fd=%d invalid input: addr=%p,len=0x%x [return]", fd, + addr, addrlen); + return -1; + } + if ((NULL == addr) || (addrlen < 2)) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR + ("nstack connect, fd=%d invalid input: addr=%p,len=0x%x [return]", fd, + addr, addrlen); + return -1; + } + + if ((addrlen >= sizeof (struct sockaddr_in)) + && ((addr->sa_family) == AF_INET)) + { + NSSOC_LOGINF ("fd=%d,addr=%s,port=%d", fd, inet_ntoa (iaddr->sin_addr), + ntohs (iaddr->sin_port)); + } + else + { + NSSOC_LOGINF ("addrlen = %d ,fd=%d", (int) addrlen, fd); + } + + /* need check addrlen's validity, will visite iaddr->sin_addr.s_addr following code,for visite iaddr->sin_addr.s_addr is 8 byte */ + if (addrlen < 8) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR + ("nstack connect, fd=%d invalid addrlen input: addr=%p,len=0x%x [return]", + fd, addr, addrlen); + return -1; + } + + if (NSTACK_ANY_IP == iaddr->sin_addr.s_addr) + { + nstack_set_errno (ECONNREFUSED); + NSSOC_LOGERR + ("nstack connect, fd=%d invalid input: 0==addr_in->sin_addr.s_addr [return]", + fd); + return -1; + } + else if (NSTACK_MAX_U32_NUM == iaddr->sin_addr.s_addr) + { + nstack_set_errno (ENETUNREACH); + NSSOC_LOGERR + ("nstack connect, fd=%d invalid input: 0xffffffff==addr_in->sin_addr.s_addr [return]", + fd); + return -1; + } + NSTACK_FD_LINUX_CHECK (fd, connect, fdInf, (fd, addr, addrlen)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_CONNECT (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_CONNECT (fd, connect, fdInf, ENOTSOCK, + local_lock); + + /*if no module select, according to dest ip */ + if (!fdInf->ops) + { + rdkey.type = RD_DATA_TYPE_IP; + rdkey.ip_addr = iaddr->sin_addr.s_addr; + retval = nstack_rd_get_stackid (&rdkey, &selectmod); + if (ns_success == retval && selectmod >= 0) + { + NSSOC_LOGINF ("fd=%d addr=%s Select module=%s", + fd, inet_ntoa (iaddr->sin_addr), + nstack_get_module_name_by_idx (selectmod)); + /*in case of that multi-thread connect. if route was chosed by one thread, the other just use the first one */ + fdInf->rmidx = selectmod; + fdInf->ops = nstack_module_ops (selectmod); + nstack_set_routed_fd (fdInf, nstack_get_protoFd (fdInf, selectmod)); + nstack_set_router_protocol (fdInf, selectmod); + } + else + { + NSSOC_LOGERR ("fd=%d Callback select module=%d ret=0x%x", fd, + selectmod, retval); + nstack_set_errno (ENETUNREACH); + UNLOCK_CONNECT (fd, local_lock); + return -1; + } + NSSOC_LOGINF ("fd=%d addr=%s Select module=%s", + fd, inet_ntoa (iaddr->sin_addr), + nstack_get_module_name_by_idx (selectmod)); + } + + NSTACK_CAL_FUN (fdInf->ops, connect, (fdInf->rlfd, addr, addrlen), retval); + if (-1 == retval && errno != EINPROGRESS) + { + NSSOC_LOGERR ("appfd=%d,module=%s,proto_fd=%d,ret=%d,errno=%d [return]", + fd, nstack_get_module_name_by_idx (fdInf->rmidx), + fdInf->rlfd, retval, errno); + } + else + { + NSSOC_LOGINF ("appfd=%d,module=%s,proto_fd=%d,ret=%d,errno=%d [return]", + fd, nstack_get_module_name_by_idx (fdInf->rmidx), + fdInf->rlfd, retval, errno); + } + UNLOCK_CONNECT (fd, local_lock); + return retval; +} + +int +nstack_shutdown (int fd, int how) +{ + nstack_fd_Inf *fdInf = NULL; + int retval = -1; + int tfd; + + nstack_set_tracing_contex (0, 0, fd); + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("fd=%d invalid input [return]", fd); + return -1; + } + + NSSOC_LOGINF ("(fd=%d, how=%d) [Caller]", fd, how); + + NSTACK_FD_LINUX_CHECK (fd, shutdown, fdInf, (fd, how)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_COMMON (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_COMMON (fd, shutdown, fdInf, ENOTSOCK, + local_lock); + + if (!fdInf->ops || -1 == fdInf->rlfd) + { + NSSOC_LOGWAR ("fd=%d,how=%d, shutdown fail [return]", fd, how); + nstack_set_errno (ENOTCONN); + UNLOCK_COMMON (fd, local_lock); + return -1; + } + tfd = fdInf->rlfd; + NSTACK_CAL_FUN (fdInf->ops, shutdown, (tfd, how), retval); + NSSOC_LOGINF ("fd=%d,ret=%d [return]", fd, retval); + UNLOCK_COMMON (fd, local_lock); + return retval; +} + +int +release_fd (int fd, nstack_fd_local_lock_info_t * local_lock) +{ + nstack_fd_Inf *fdInf = NULL; + nstack_module *pMod = NULL; + int retval = 0; + int curRet = -1; + int modInx, tfd; + + if (!local_lock) + { + return -1; + } + + LOCK_CLOSE (local_lock); + + /* if fd is used by others, just pass, delay close it */ + if (local_lock->fd_status != FD_CLOSING || local_lock->fd_ref.counter > 0) + { + UNLOCK_CLOSE (local_lock); + return 0; + } + local_lock->fd_status = FD_CLOSE; + + fdInf = nstack_fd2inf (fd); + if (NULL == fdInf) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR ("pstfdInf is NULL"); + UNLOCK_CLOSE (local_lock); + return -1; + } + + (void) nsep_epoll_close (fd); + + nstack_each_module (modInx, pMod) + { + tfd = nstack_get_protoFd (fdInf, modInx); + + if (nstack_get_minfd_id (modInx) > tfd + || tfd > nstack_get_maxfd_id (modInx)) + { + continue; + } + + NSSOC_LOGINF ("fd=%d,module=%s,tfd=%d", fd, + nstack_get_module_name_by_idx (modInx), tfd); + + if (0 == + strcmp (nstack_fix_stack_name (), + nstack_get_module_name_by_idx (modInx))) + { + continue; + } + + nssct_close (fd, modInx); + NSTACK_CAL_FUN ((&pMod->mops.socket_ops), close, (tfd), curRet); + + if (-1 == curRet) + { + NSSOC_LOGERR ("failed]module=%s,tfd=%d,errno=%d", + nstack_get_module_name_by_idx (modInx), tfd, errno); + } + + retval &= curRet; + } + retval &= nstack_fd_free_with_kernel (fdInf); + if (-1 == retval) + { + NSSOC_LOGWAR ("fd=%d,ret=%d [return]", fd, retval); + } + else + { + NSSOC_LOGINF ("fd=%d,ret=%d [return]", fd, retval); + } + + UNLOCK_CLOSE (local_lock); + return retval; +} + +/*not support fork now, to support fork the module must provide gfdt & refer cnt + while fork the frame use callback fun to add refer*/ +int +nstack_close (int fd) +{ + nstack_fd_Inf *fdInf; + int ret = -1; + nstack_set_tracing_contex (0, 0, fd); + + /*linux fd check */ + if (!(fdInf = nstack_getValidInf (fd))) + { + if (NSTACK_THREAD_LOADING ()) + { + return nsfw_base_close (fd); + } + if (0 != nstack_stack_module_load ()) + { + return -1; + } + if (nstack_fix_fd_check () + && nstack_fix_fd_check ()(fd, STACK_FD_FUNCALL_CHECK)) + { + /*free epoll resouce */ + nsep_epoll_close (fd); + nssct_close (fd, nstack_get_fix_mid ()); + + NSTACK_CAL_FUN (nstack_fix_mid_ops (), close, (fd), ret); + return ret; + } + nstack_set_errno (ENOSYS); + return -1; + } + + NSSOC_LOGINF ("Caller]fd=%d", fd); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_CLOSE (local_lock); + if (local_lock->fd_status != FD_OPEN) + { + NSSOC_LOGERR ("return]fd_status=%d,fd=%d", local_lock->fd_status, fd); + nstack_set_errno (EBADF); + UNLOCK_CLOSE (local_lock); + return -1; + } + + set_fd_status_lock_fork (fd, FD_CLOSING); + + UNLOCK_CLOSE (local_lock); + ret = + (atomic_dec (&local_lock->fd_ref) > 0 ? 0 : release_fd (fd, local_lock)); + + if (-1 == ret) + { + NSSOC_LOGWAR ("return]fd=%d,retVal=%d", fd, ret); + } + else + { + NSSOC_LOGINF ("return]fd=%d,retVal=%d", fd, ret); + } + + return ret; +} + +ssize_t +nstack_send (int fd, const void *buf, size_t len, int flags) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_SEND, NSOCKET, "NSSOC", NSLOG_DBG, + "(sockfd=%d, buf=%p, len=%zu, flags=%d) [Caller]", fd, buf, + len, flags); + + NSTACK_FD_LINUX_CHECK (fd, send, fdInf, (fd, buf, len, flags)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_SEND (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_SEND (fd, send, fdInf, ENOTSOCK, + local_lock); + + if ((!fdInf->ops) || (-1 == fdInf->rlfd)) + { + NSSOC_LOGINF ("fd Fail: Not select any module yet!]fd=%d [return]", fd); + nstack_set_errno (ENOTCONN); + UNLOCK_SEND (fd, local_lock); + return -1; + } + + /* *INDENT-OFF* */ + CPUB(stack_x_send) + NSTACK_CAL_FUN(fdInf->ops, send, (fdInf->rlfd, buf, len, flags), size); + CPUE(stack_x_send) + /* *INDENT-ON* */ + NSSOC_LOGDBG ("fd=%d,ret=%d [Return]", fd, size); + + UNLOCK_SEND (fd, local_lock); + return size; +} + +ssize_t +nstack_recv (int fd, void *buf, size_t len, int flags) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_RECV, NSOCKET, "NSSOC", NSLOG_DBG, + "(sockfd=%d, buf=%p, len=%zu, flags=%d) [Caller]", fd, buf, + len, flags); + + NSTACK_FD_LINUX_CHECK (fd, recv, fdInf, (fd, buf, len, flags)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_RECV (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_RECV (fd, recv, fdInf, ENOTSOCK, + local_lock); + + if ((!fdInf->ops) || (-1 == fdInf->rlfd)) + { + NSSOC_LOGINF ("Not select any module yet!]fd=%d [Return]", fd); + nstack_set_errno (ENOTCONN); + UNLOCK_RECV (fd, local_lock); + return -1; + } + + /* *INDENT-OFF* */ + CPUB(stack_x_recv) + NSTACK_CAL_FUN(fdInf->ops, recv, (fdInf->rlfd, buf, len, flags), size); + CPUE(stack_x_recv) + /* *INDENT-ON* */ + NSSOC_LOGDBG ("fd=%d,ret=%d [Return]", fd, size); + + UNLOCK_RECV (fd, local_lock); + return size; +} + +ssize_t +nstack_write (int fd, const void *buf, size_t count) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + + NSTACK_FD_LINUX_CHECK (fd, write, fdInf, (fd, buf, count)); + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_WRITE, NSOCKET, "NSSOC", NSLOG_DBG, + "(fd=%d, buf=%p, count=%zu) [Caller]", fd, buf, count); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_SEND (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_SEND (fd, write, fdInf, EINVAL, + local_lock); + + if ((!fdInf->ops) || (-1 == fdInf->rlfd)) + { + NSSOC_LOGINF ("Not select any module yet!]fd=%d [Return]", fd); + nstack_set_errno (ENOTCONN); + UNLOCK_SEND (fd, local_lock); + return -1; + } + + /* *INDENT-OFF* */ + CPUB(stack_x_write) + NSTACK_CAL_FUN(fdInf->ops, write, (fdInf->rlfd, buf, count), size); + CPUE(stack_x_write) + /* *INDENT-ON* */ + + NSSOC_LOGDBG ("fd=%d,ret=%d [Return]", fd, size); + + UNLOCK_SEND (fd, local_lock); + return size; +} + +ssize_t +nstack_read (int fd, void *buf, size_t count) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_READ, NSOCKET, "NSSOC", NSLOG_DBG, + "(fd=%d, buf=%p, count=%zu) [Caller]", fd, buf, count); + + NSTACK_FD_LINUX_CHECK (fd, read, fdInf, (fd, buf, count)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_RECV (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_RECV (fd, read, fdInf, EINVAL, local_lock); + + if ((!fdInf->ops) || (-1 == fdInf->rlfd)) + { + NSSOC_LOGINF ("Not select any module yet!]fd=%d [Return]", fd); + nstack_set_errno (ENOTCONN); + UNLOCK_RECV (fd, local_lock); + return -1; + } + + /* *INDENT-OFF* */ + CPUB(stack_x_read) + NSTACK_CAL_FUN(fdInf->ops, read, (fdInf->rlfd, buf, count), size); + CPUE(stack_x_read) + /* *INDENT-ON* */ + + NSSOC_LOGDBG ("fd=%d,ret=%d [Return]", fd, size); + + UNLOCK_RECV (fd, local_lock); + return size; +} + +ssize_t +nstack_writev (int fd, const struct iovec * iov, int iovcnt) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_WRITEV, NSOCKET, "NSSOC", NSLOG_DBG, + "(fd=%d, iov=%p, count=%d) [Caller]", fd, iov, iovcnt); + + NSTACK_FD_LINUX_CHECK (fd, writev, fdInf, (fd, iov, iovcnt)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_SEND (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_SEND (fd, writev, fdInf, EINVAL, + local_lock); + + if ((!fdInf->ops) || (-1 == fdInf->rlfd)) + { + NSSOC_LOGERR ("Not select any module yet!]fd=%d [Return]", fd); + nstack_set_errno (ENOTCONN); + UNLOCK_SEND (fd, local_lock); + return -1; + } + + /* *INDENT-OFF* */ + CPUB(stack_x_writev) + NSTACK_CAL_FUN(fdInf->ops, writev, (fdInf->rlfd, iov, iovcnt), size); + CPUE(stack_x_writev) + /* *INDENT-ON* */ + + NSSOC_LOGDBG ("fd=%d,ret=%d [Return]", fd, size); + + UNLOCK_SEND (fd, local_lock); + return size; +} + +ssize_t +nstack_readv (int fd, const struct iovec * iov, int iovcnt) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_READV, NSOCKET, "NSSOC", NSLOG_DBG, + "(fd=%d, iov=%p, count=%d) [Caller]", fd, iov, iovcnt); + + NSTACK_FD_LINUX_CHECK (fd, readv, fdInf, (fd, iov, iovcnt)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_RECV (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_RECV (fd, readv, fdInf, EINVAL, + local_lock); + + if ((!fdInf->ops) || (-1 == fdInf->rlfd)) + { + NSSOC_LOGERR ("Not select any module yet!]fd=%d [Return]", fd); + nstack_set_errno (ENOTCONN); + UNLOCK_RECV (fd, local_lock); + return -1; + } + + /* *INDENT-OFF* */ + CPUB(stack_x_readv) + NSTACK_CAL_FUN(fdInf->ops, readv, (fdInf->rlfd, iov, iovcnt), size); + CPUE(stack_x_readv) + /* *INDENT-ON* */ + + NSSOC_LOGDBG ("fd=%d,ret=%d [Return]", fd, size); + + UNLOCK_RECV (fd, local_lock); + return size; +} + +/*we assumed that the connect allready called, if not call, we must try many sok*/ +ssize_t +nstack_sendto (int fd, const void *buf, size_t len, int flags, + const struct sockaddr * dest_addr, socklen_t addrlen) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + struct sockaddr_in *iaddr = NULL; + int selectmod = -1; + int retval = 0; + nstack_rd_key rdkey = { 0 }; + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGDBG + ("(sockfd=%d, buf=%p, len=%zu, flags=%d, dest_addr=%p, addrlen=%u) [Caller]", + fd, buf, len, flags, dest_addr, addrlen); + + NSTACK_FD_LINUX_CHECK (fd, sendto, fdInf, + (fd, buf, len, flags, dest_addr, addrlen)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_SEND (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_SEND (fd, sendto, fdInf, ENOTSOCK, + local_lock); + + if (fdInf->ops) + { + /* *INDENT-OFF* */ + CPUB(stack_x_sendto) + NSTACK_CAL_FUN(fdInf->ops, sendto, (fdInf->rlfd, buf, len, flags, dest_addr, addrlen), size); + CPUE(stack_x_sendto) + /* *INDENT-ON* */ + + NSSOC_LOGDBG + ("fdInf->ops:fd=%d buf=%p,len=%zu,size=%d,addr=%p [Return]", fd, buf, + len, size, dest_addr); + UNLOCK_SEND (fd, local_lock); + return size; + } + /*invalid ip, just return */ + /*validity check for addrlen: for visite iaddr->sin_addr.s_addr is 8 byte */ + if ((NULL == dest_addr) || (addrlen < 8)) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR ("invalid input]fd=%d,buf=%p,len=%zu,addr=%p [Return]", fd, + buf, len, dest_addr); + UNLOCK_SEND (fd, local_lock); + return -1; + } + + iaddr = (struct sockaddr_in *) dest_addr; + rdkey.type = RD_DATA_TYPE_IP; + rdkey.ip_addr = iaddr->sin_addr.s_addr; + retval = nstack_rd_get_stackid (&rdkey, &selectmod); + if ((ns_success == retval) && (selectmod >= 0)) + { + NSSOC_LOGINF ("fd=%d,addr=%s,select_module=%s", + fd, inet_ntoa (iaddr->sin_addr), + nstack_get_module_name_by_idx (selectmod)); + fdInf->rmidx = selectmod; + nstack_set_routed_fd (fdInf, nstack_get_protoFd (fdInf, selectmod)); + nstack_set_router_protocol (fdInf, selectmod); + fdInf->ops = nstack_module_ops (selectmod); + } + else + { + NSSOC_LOGERR ("fd=%d Callback select module=%d,ret=0x%x", fd, selectmod, + retval); + nstack_set_errno (ENETUNREACH); + UNLOCK_SEND (fd, local_lock); + return -1; + } + + NSSOC_LOGDBG ("fd=%d,addr=%s,select_module=%s", + fd, inet_ntoa (iaddr->sin_addr), + nstack_get_module_name_by_idx (selectmod)); + + NSTACK_CAL_FUN (fdInf->ops, sendto, + (fdInf->rlfd, buf, len, flags, dest_addr, addrlen), size); + + NSSOC_LOGDBG ("fd=%d,module=%s,ret=%d [Return]", fd, + nstack_get_module_name_by_idx (fdInf->rmidx), size); + + UNLOCK_SEND (fd, local_lock); + return size; +} + +ssize_t +nstack_sendmsg (int fd, const struct msghdr * msg, int flags) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + struct sockaddr_in *iaddr = NULL; + int selectmod = -1; + int retval = 0; + nstack_rd_key rdkey = { 0 }; + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_SENDMSG, NSOCKET, "NSSOC", NSLOG_DBG, + "(sockfd=%d, msg=%p, flags=%d) [Caller]", fd, msg, flags); + + if (NULL == msg) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR ("invalid input]fd=%d,msg=%p [Return]", fd, msg); + return -1; + } + + NSTACK_FD_LINUX_CHECK (fd, sendmsg, fdInf, (fd, msg, flags)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_SEND (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_SEND (fd, sendmsg, fdInf, ENOTSOCK, + local_lock); + + /*if some module select, just connect */ + if (fdInf->ops) + { + /* *INDENT-OFF* */ + CPUB(stack_x_sendmsg) + NSTACK_CAL_FUN(fdInf->ops, sendmsg, (fdInf->rlfd, msg, flags), size); + CPUE(stack_x_sendmsg) + /* *INDENT-ON* */ + NSSOC_LOGDBG ("]fd=%d,size=%d msg=%p [Return]", fd, size, msg); + UNLOCK_SEND (fd, local_lock); + return size; + } + + iaddr = (struct sockaddr_in *) msg->msg_name; + /* validity check for msg->msg_namelen,for visite iaddr->sin_addr.s_addr is 8 byte */ + if ((NULL == iaddr) || (msg->msg_namelen < 8)) + { + NSSOC_LOGINF ("fd addr is null and select linux module]fd=%d", fd); + fdInf->ops = nstack_module_ops (nstack_get_fix_mid ()); + nstack_set_routed_fd (fdInf, + nstack_get_protoFd (fdInf, + nstack_get_fix_mid ())); + nstack_set_router_protocol (fdInf, nstack_get_fix_mid ()); + } + else + { + rdkey.type = RD_DATA_TYPE_IP; + rdkey.ip_addr = iaddr->sin_addr.s_addr; + retval = nstack_rd_get_stackid (&rdkey, &selectmod); + if (ns_success == retval) + { + NSSOC_LOGINF ("fd=%d,addr=%s,select_module=%s", + fd, inet_ntoa (iaddr->sin_addr), + nstack_get_module_name_by_idx (selectmod)); + fdInf->rmidx = selectmod; + nstack_set_routed_fd (fdInf, nstack_get_protoFd (fdInf, selectmod)); + nstack_set_router_protocol (fdInf, selectmod); + fdInf->ops = nstack_module_ops (selectmod); + } + else + { + NSSOC_LOGERR ("fd=%d Callback select_module=%d,ret=0x%x", fd, + selectmod, retval); + nstack_set_errno (ENETUNREACH); + UNLOCK_SEND (fd, local_lock); + return -1; + } + NSSOC_LOGDBG ("fd=%d,addr=%s,select_module=%s", + fd, inet_ntoa (iaddr->sin_addr), + nstack_get_module_name_by_idx (selectmod)); + } + + NSTACK_CAL_FUN (fdInf->ops, sendmsg, (fdInf->rlfd, msg, flags), size); + + NSSOC_LOGDBG ("fd=%d,module=%s,ret=%d [Return]", fd, + nstack_get_module_name_by_idx (fdInf->rmidx), size); + + UNLOCK_SEND (fd, local_lock); + return size; +} + +/*we assumed that the connect allready called, if not call, we must try many sok*/ +ssize_t +nstack_recvfrom (int fd, void *buf, size_t len, int flags, + struct sockaddr * src_addr, socklen_t * addrlen) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGDBG + ("(sockfd=%d, buf=%p, len=%zu, flags=%d, src_addr=%p, addrlen=%p) [Caller]", + fd, buf, len, flags, src_addr, addrlen); + + if (NULL == buf) + { + nstack_set_errno (EFAULT); + NSSOC_LOGERR ("invalid input]fd=%d,buf=%p [Return]", fd, buf); + return -1; + } + + NSTACK_FD_LINUX_CHECK (fd, recvfrom, fdInf, + (fd, buf, len, flags, src_addr, addrlen)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_RECV (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_RECV (fd, recvfrom, fdInf, ENOTSOCK, + local_lock); + + if ((!fdInf->ops) || (-1 == fdInf->rlfd)) + { + NSSOC_LOGINF ("Not select any module yet!]fd=%d [Return]", fd); + nstack_set_errno (ENOTCONN); + UNLOCK_RECV (fd, local_lock); + return -1; + } + + /* *INDENT-OFF* */ + CPUB(stack_x_recvfrom) + NSTACK_CAL_FUN(fdInf->ops, recvfrom, (fdInf->rlfd, buf, len, flags, src_addr, addrlen), size); + CPUE(stack_x_recvfrom) + /* *INDENT-ON* */ + + NSSOC_LOGDBG ("fd=%d,retVal=%d [Return]", fd, size); + + UNLOCK_RECV (fd, local_lock); + return size; +} + +ssize_t +nstack_recvmsg (int fd, struct msghdr * msg, int flags) +{ + nstack_fd_Inf *fdInf = NULL; + int size = -1; + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_RECVMSG, NSOCKET, "NSSOC", NSLOG_DBG, + "(sockfd=%d, msg=%p, flags=%d) [Caller]", fd, msg, flags); + + NSTACK_FD_LINUX_CHECK (fd, recvmsg, fdInf, (fd, msg, flags)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_RECV (fd, fdInf, local_lock); + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_RECV (fd, recvmsg, fdInf, ENOTSOCK, + local_lock); + + if ((-1 == fdInf->rlfd) || (NULL == fdInf->ops)) + { + NSSOC_LOGERR ("Not select any module yet!]fd=%d [Return]", fd); + nstack_set_errno (ENOTCONN); + UNLOCK_RECV (fd, local_lock); + return -1; + } + + /* *INDENT-OFF* */ + CPUB(stack_x_recvmsg) + NSTACK_CAL_FUN(fdInf->ops, recvmsg, (fdInf->rlfd, msg, flags), size); + CPUE(stack_x_recvmsg) + /* *INDENT-ON* */ + + NSSOC_LOGDBG ("fd=%d,ret=%d [Return]", fd, size); + + UNLOCK_RECV (fd, local_lock); + return size; +} + +/***************************************************************** +Parameters : fd + addr + len +Return : +Description : all module fd bind to same addr, so just use first rlfd to get bind addr. +*****************************************************************/ +int +nstack_getsockname (int fd, struct sockaddr *addr, socklen_t * addrlen) +{ + nstack_fd_Inf *fdInf = NULL; + int tfd = -1; + int ret = -1; + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_GETSOCKNAME, NSOCKET, "NSSOC", NSLOG_INF, + "(fd=%d, addr=%p, addrlen=%p) [Caller]", fd, addr, addrlen); + + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("invalid input]fd=%d. [return]", fd); + return -1; + } + + NSTACK_FD_LINUX_CHECK (fd, getsockname, fdInf, (fd, addr, addrlen)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_COMMON (fd, fdInf, local_lock); + + if ((NULL != fdInf->ops) && (fdInf->rlfd != -1)) + { + tfd = fdInf->rlfd; + NSTACK_CAL_FUN (fdInf->ops, getsockname, (tfd, addr, addrlen), ret); + NSSOC_LOGINF ("fd=%d,module=%s,tfd=%d [return]", fd, + nstack_get_module_name_by_idx (fdInf->rmidx), tfd); + if (-1 == ret) + { + NSSOC_LOGERR ("rmidx=%d,fd=%d return fail [return]", fdInf->rmidx, + tfd); + } + UNLOCK_COMMON (fd, local_lock); + return ret; + } + + if (NULL != g_nstack_modules.defMod) + { + tfd = nstack_get_protoFd (fdInf, nstack_defMod_inx ()); + if (tfd >= 0) + { + nstack_socket_ops *ops = nstack_def_ops (); + NSTACK_CAL_FUN (ops, getsockname, (tfd, addr, addrlen), ret); + NSSOC_LOGINF ("fd=%d,module=%s,tfd=%d [return]", fd, + nstack_defmod_name (), tfd); + if (-1 == ret) + { + NSSOC_LOGERR ("return fail]mudle=%d,fd=%d [return]", + nstack_defMod_inx (), tfd); + } + UNLOCK_COMMON (fd, local_lock); + return ret; + } + } + + nstack_set_errno (ENOTSOCK); + NSSOC_LOGINF ("fd=%d,ret=%d [Return]", fd, ret); + UNLOCK_COMMON (fd, local_lock); + return ret; + +} + +/***************************************************************** +Parameters : fd + addr + len +Return : +Description : getpeername only used by the fd who already Estblsh connection, so use first rlfd. +*****************************************************************/ +int +nstack_getpeername (int fd, struct sockaddr *addr, socklen_t * addrlen) +{ + nstack_fd_Inf *fdInf; + int tfd; + int ret = -1; + + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_GETPEERNAME, NSOCKET, "NSSOC", NSLOG_INF, + "(fd=%d, addr=%p, addrlen=%p) [Caller]", fd, addr, addrlen); + + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("invalid input, fd=%d. [return]", fd); + return -1; + } + + NSTACK_FD_LINUX_CHECK (fd, getpeername, fdInf, (fd, addr, addrlen)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_COMMON (fd, fdInf, local_lock); + + /*?????????,????????????? */ + if (fdInf->ops) + { + tfd = fdInf->rlfd; + NSTACK_CAL_FUN (fdInf->ops, getpeername, (tfd, addr, addrlen), ret); + NSSOC_LOGINF ("fd=%d,module=%s,rlfd=%d,ret=%d [return]", + fd, nstack_get_module_name_by_idx (fdInf->rmidx), + fdInf->rlfd, ret); + if (-1 == ret) + { + NSSOC_LOGERR ("return fail]mudle=%d,fd=%d [return]", fdInf->rmidx, + tfd); + } + UNLOCK_COMMON (fd, local_lock); + return ret; + } + + if (NULL != g_nstack_modules.defMod) + { + tfd = nstack_get_protoFd (fdInf, nstack_defMod_inx ()); + if (tfd >= 0) + { + nstack_socket_ops *ops = nstack_def_ops (); + NSTACK_CAL_FUN (ops, getpeername, (tfd, addr, addrlen), ret); + NSSOC_LOGINF ("fd=%d,module=%s,tfd=%d [return]", fd, + nstack_defmod_name (), tfd); + if (-1 == ret) + { + NSSOC_LOGERR ("return fail] mudle=%d,fd=%d [return]", + nstack_defMod_inx (), tfd); + } + UNLOCK_COMMON (fd, local_lock); + return ret; + } + } + + nstack_set_errno (ENOTSOCK); + NSSOC_LOGINF ("fd=%d,ret=%d [Return]", fd, ret); + UNLOCK_COMMON (fd, local_lock); + return ret; +} + +int +nstack_option_set (nstack_fd_Inf * fdInf, int optname, const void *optval, + socklen_t optlen) +{ + +#define SLEEP_MAX 10000000 + if ((!optval) || (optlen < sizeof (u32_t))) + { + NSSOC_LOGINF ("rong parmeter optname]=%d", optname); + nstack_set_errno (EINVAL); + return -1; + } + + switch (optname) + { + case NSTACK_SEM_SLEEP: + if ((*(u32_t *) optval) > SLEEP_MAX) + { + NSSOC_LOGWAR ("time overflow]epfd=%d", fdInf->fd); + nstack_set_errno (EINVAL); + return -1; + } + + nsep_set_infoSleepTime (fdInf->fd, *(u32_t *) optval); + NSSOC_LOGINF ("set sem wait option] g_sem_sleep_time=%ld", + *(u32_t *) optval); + break; + + default: + NSSOC_LOGINF ("rong parmeter optname]=%d", optname); + nstack_set_errno (ENOPROTOOPT); + return -1; + } + return 0; +} + +int +nstack_option_get (nstack_fd_Inf * fdInf, int optname, const void *optval, + socklen_t * optlen) +{ + + if ((!optval) || (!optlen) || (optlen && (*optlen < sizeof (u32_t)))) + { + NSSOC_LOGINF ("rong parmeter optname]=%d", optname); + nstack_set_errno (EINVAL); + return -1; + } + + switch (optname) + { + case NSTACK_SEM_SLEEP: + *(long *) optval = nsep_get_infoSleepTime (fdInf->fd); + NSSOC_LOGINF ("get sem wait option] g_sem_sleep_time=%ld", + *(long *) optval); + break; + + default: + NSSOC_LOGINF ("rong parmeter optname]=%d", optname); + nstack_set_errno (ENOPROTOOPT); + return -1; + } + return 0; +} + +/* just use first rlfd to getsockopt, this may not what app really want.*/ +/* Currently, if getsockopt is successfull either in kernel or stack-x, the below API returns SUCCESS */ +int +nstack_getsockopt (int fd, int level, int optname, void *optval, + socklen_t * optlen) +{ + nstack_fd_Inf *fdInf; + int tfd; + int ret = -1; + nstack_socket_ops *ops; + nstack_set_tracing_contex (0, 0, fd); + NS_LOG_CTRL (LOG_CTRL_GETSOCKOPT, NSOCKET, "NSSOC", NSLOG_INF, + "(fd=%d, level=%d, optname=%d, optval=%p, optlen=%p) [Caller]", + fd, level, optname, optval, optlen); + + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("invalid input]fd=%d [return]", fd); + return -1; + } + + NSTACK_FD_LINUX_CHECK (fd, getsockopt, fdInf, + (fd, level, optname, optval, optlen)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_COMMON (fd, fdInf, local_lock); + + if ((NSTACK_SOCKOPT == level) && NSTACK_IS_FD_EPOLL_SOCKET (fdInf)) + { + ret = nstack_option_get (fdInf, optname, optval, optlen); + UNLOCK_COMMON (fd, local_lock); + return ret; + } + + if (fdInf->ops) + { + tfd = fdInf->rlfd; + NSTACK_CAL_FUN (fdInf->ops, getsockopt, + (tfd, level, optname, optval, optlen), ret); + NSSOC_LOGINF + ("fd=%d,module=%s,tfd=%d,level=%d,optname=%d,ret=%d [return]", fd, + nstack_get_module_name_by_idx (fdInf->rmidx), tfd, level, optname, + ret); + if (-1 == ret) + { + NSSOC_LOGERR ("return fail]mudle=%d,fd=%d [return]", fdInf->rmidx, + tfd); + } + UNLOCK_COMMON (fd, local_lock); + return ret; + } + + if (NULL != g_nstack_modules.defMod) + { + tfd = nstack_get_protoFd (fdInf, nstack_defMod_inx ()); + if (tfd >= 0) + { + ops = nstack_def_ops (); + NSTACK_CAL_FUN (ops, getsockopt, + (tfd, level, optname, optval, optlen), ret); + NSSOC_LOGINF + ("fd=%d,module=%s:%d,level=%d,optname=%d,ret=%d [return]", fd, + nstack_defmod_name (), tfd, level, optname, ret); + if (-1 == ret) + { + NSSOC_LOGERR ("return fail]mudle=%d,fd=%d [return]", + nstack_defMod_inx (), tfd); + } + UNLOCK_COMMON (fd, local_lock); + return ret; + } + } + + nstack_set_errno (ENOTSOCK); + NSSOC_LOGINF ("fd=%d,ret=%d [Return]", fd, ret); + UNLOCK_COMMON (fd, local_lock); + return ret; +} + +/* all rlfd need setsockopt, set opt failed still can Estblsh connection. so we not care suc/fail */ +/* Currently, if setsockopt is successfull either in kernel or stack-x, the below API returns SUCCESS */ +int +nstack_setsockopt (int fd, int level, int optname, const void *optval, + socklen_t optlen) +{ + nstack_fd_Inf *fdInf; + int ret = -1; + nstack_socket_ops *ops; + int itfd; + int modInx = 0; + int curRet = -1; + int lerror = 0; + int flag = 0; + + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGINF + ("(fd=%d, level=%d, optname=%d, optval=%p, optlen=%u) [Caller]", fd, + level, optname, optval, optlen); + + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("invalid input]fd=%d [return]", fd); + return -1; + } + + NSTACK_FD_LINUX_CHECK (fd, setsockopt, fdInf, + (fd, level, optname, optval, optlen)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_COMMON (fd, fdInf, local_lock); + + if ((NSTACK_SOCKOPT == level) && NSTACK_IS_FD_EPOLL_SOCKET (fdInf)) + { + ret = nstack_option_set (fdInf, optname, optval, optlen); + UNLOCK_COMMON (fd, local_lock); + return ret; + } + + if (fdInf->ops) + { + itfd = fdInf->rlfd; + NSTACK_CAL_FUN (fdInf->ops, setsockopt, + (itfd, level, optname, optval, optlen), ret); + NSSOC_LOGINF + ("fd=%d,module=%s,tfd=%d,level=%d,optname=%d,ret=%d [return]", fd, + nstack_get_module_name_by_idx (fdInf->rmidx), itfd, level, optname, + ret); + if (-1 == ret) + { + NSSOC_LOGERR ("return fail]mudle=%d,fd=%d [return]", fdInf->rmidx, + itfd); + } + UNLOCK_COMMON (fd, local_lock); + return ret; + } + nstack_each_modOps (modInx, ops) + { + itfd = nstack_get_protoFd (fdInf, modInx); + if (-1 == itfd) + { + continue; + } + flag = 1; + NSTACK_CAL_FUN (ops, setsockopt, (itfd, level, optname, optval, optlen), + curRet); + NSSOC_LOGDBG ("fd=%d,module=%s,tfd=%d,level=%d,optname=%d,ret=%d", fd, + nstack_get_module_name_by_idx (modInx), itfd, level, + optname, curRet); + if (modInx == nstack_get_fix_mid ()) + { + ret = curRet; + /* errno is thread safe, but stack-x is not, so save it first */ + lerror = errno; + } + } + /* errno is thread safe, but stack-x is not, so save it first begin */ + /*if all fd of stack is -1, the input fd maybe invalid */ + if (0 == flag) + { + nstack_set_errno (EBADF); + } + /*if linux return fail, and error is none zero, just reset it again */ + if ((lerror != 0) && (ns_success != ret)) + { + nstack_set_errno (lerror); + } + /* errno is thread safe, but stack-x is not, so save it first end */ + NSSOC_LOGINF ("fd=%d,ret=%d [Return]", fd, ret); + UNLOCK_COMMON (fd, local_lock); + return ret; +} + +int +nstack_ioctl (int fd, unsigned long request, unsigned long argp) +{ + nstack_fd_Inf *fdInf; + int ret = -1; + nstack_socket_ops *ops; + int tfd; + int modInx = 0; + int curRet = -1; + int lerror = 0; + int flag = 0; + + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGINF ("(fd=%d, request=%lu) [Caller]", fd, request); + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("invalid input]fd=%d [return]", fd); + return -1; + } + + NSTACK_FD_LINUX_CHECK (fd, ioctl, fdInf, (fd, request, argp)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + + LOCK_COMMON (fd, fdInf, local_lock); + if (fdInf->ops) + { + tfd = fdInf->rlfd; + NSTACK_CAL_FUN (fdInf->ops, ioctl, (tfd, request, argp), ret); + NSSOC_LOGINF ("fd=%d,module=%s,rlfd=%d,argp=0x%x,ret=%d [return]", + fd, nstack_get_module_name_by_idx (fdInf->rmidx), + fdInf->rlfd, argp, ret); + if (-1 == ret) + { + NSSOC_LOGERR ("return fail]mudle=%d,fd=%d [return]", fdInf->rmidx, + tfd); + } + + UNLOCK_COMMON (fd, local_lock); + return ret; + } + + nstack_each_modOps (modInx, ops) + { + tfd = nstack_get_protoFd (fdInf, modInx); + if (-1 == tfd) + { + continue; + } + flag = 1; + + NSTACK_CAL_FUN (ops, ioctl, (tfd, request, argp), curRet); + NSSOC_LOGINF ("fd=%d,module=%s,tfd=%d,argp=0x%x,ret=%d ", + fd, nstack_get_module_name_by_idx (modInx), tfd, argp, + curRet); + if (modInx == nstack_get_fix_mid ()) + { + ret = curRet; + /* errno is thread safe, but stack-x is not, so save it first */ + lerror = errno; + } + } + /* errno is thread safe, but stack-x is not, so save it first */ + if (0 == flag) + { + nstack_set_errno (EBADF); + } + if ((0 != lerror) && (ns_success != ret)) + { + nstack_set_errno (lerror); + } + + NSSOC_LOGINF ("fd=%d,ret=%d [return]", fd, ret); + + UNLOCK_COMMON (fd, local_lock); + return ret; +} + +int +nstack_fcntl (int fd, int cmd, unsigned long argp) +{ + nstack_fd_Inf *fdInf; + nstack_socket_ops *ops = NULL; + int ret = -1; + int noProOpt = 0; + int tfd; + int modInx = 0; + int curRet = -1; + int lerror = 0; + int flag = 0; + + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGINF ("(fd=%d, cmd=%d) [Caller]", fd, cmd); + if (fd < 0) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("invalid input]fd=%d [return]", fd); + return -1; + } + + NSTACK_FD_LINUX_CHECK (fd, fcntl, fdInf, (fd, cmd, argp)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_COMMON (fd, fdInf, local_lock); + + /*have already bind */ + if (fdInf->ops) + { + tfd = fdInf->rlfd; + NSTACK_CAL_FUN (fdInf->ops, fcntl, (tfd, cmd, argp), ret); + NSSOC_LOGINF ("fd=%d,cmd=%d,mod=%s,tfd=%d,argp=0x%x,ret=%d", + fd, cmd, nstack_get_module_name_by_idx (fdInf->rmidx), + tfd, argp, ret); + if (-1 == ret) + { + NSSOC_LOGERR ("return fail]mudle=%d,fd=%d", fdInf->rmidx, tfd); + } + } + else + { + /*set cmd call all module, and return just linux */ + if (F_SETFL == cmd) + { + nstack_each_modOps (modInx, ops) + { + tfd = nstack_get_protoFd (fdInf, modInx); + if (-1 == tfd) + { + continue; + } + flag = 1; + noProOpt = 0; + NSTACK_CAL_FUN (ops, fcntl, (tfd, cmd, argp), curRet); + NSSOC_LOGINF ("fd=%d,module=%s,tfd=%d,argp=0x%x,ret=%d ", + fd, nstack_get_module_name_by_idx (modInx), tfd, + argp, curRet); + if (modInx == nstack_get_fix_mid ()) + { + ret = curRet; + lerror = errno; + } + } + /* errno is thread safe, but stack-x is not, so save it first */ + if (0 == flag) + { + nstack_set_errno (EBADF); + } + if ((0 != lerror) && (ns_success != ret)) + { + nstack_set_errno (lerror); + } + } /*other cmd call default */ + else if (g_nstack_modules.defMod) + { + tfd = nstack_get_protoFd (fdInf, g_nstack_modules.defMod->modInx); + if (tfd >= 0) + { + ops = nstack_def_ops (); + NSTACK_CAL_FUN (ops, fcntl, (tfd, cmd, argp), ret); + NSSOC_LOGINF ("fd=%d,cmd=%d,mod=%s,tfd=%d,argp=0x%x,ret=%d", + fd, cmd, g_nstack_modules.defMod->modulename, tfd, + argp, ret); + if (-1 == ret) + { + NSSOC_LOGERR ("return fail]mudle=%d,fd=%d", + g_nstack_modules.defMod->modInx, tfd); + } + } + else + { + noProOpt = 1; + } + } + else + { + noProOpt = 1; + } + } + + if (noProOpt) + { + nstack_set_errno (EBADF); + NSSOC_LOGINF ("fd=%d,ret=%d", fd, ret); + } + + NSSOC_LOGINF ("fd=%d,cmd=%d,ret=%d [return]", fd, cmd, ret); + UNLOCK_COMMON (fd, local_lock); + return ret; +} + +/***************************************************************************** +* Prototype : nstack_select +* Description : nstack_select +* Input : int nfds +* fd_set *readfds +* fd_set *writefds +* fd_set *exceptfds +* struct timeval *timeout +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nstack_select (int nfds, fd_set * readfds, fd_set * writefds, + fd_set * exceptfds, struct timeval *timeout) +{ + int ret = -1; + + struct select_entry *entry = NULL; + struct select_module_info *select_module = get_select_module (); + u64_t msec; + + int i; + + nstack_set_tracing_contex (0, 0, -1); + if ((nfds > __FD_SETSIZE) || (nfds < 0) + || ((timeout) && ((timeout->tv_sec < 0) || (timeout->tv_usec < 0)))) + { + NSSOC_LOGERR ("paremeter of nfds or timeout are no correct.]nfds = %d \ + sec = %ld usec = %ld", nfds, timeout->tv_sec, timeout->tv_usec); + errno = EINVAL; + return -1; + } + + for (i = 0; i < nfds; i++) + { + if ((readfds) && (FD_ISSET (i, readfds))) + { + NSSOC_LOGDBG ("input readfd set %d", i); + } + + if ((writefds) && (FD_ISSET (i, writefds))) + { + NSSOC_LOGDBG ("input writefd set %d", i); + } + if ((exceptfds) && (FD_ISSET (i, exceptfds))) + { + NSSOC_LOGDBG ("input exceptfds set %d", i); + } + } + + /*check the module had regist or not */ + if (TRUE != NSTACK_SELECT_LINUX_CHECK ()) + { + return nsfw_base_select (nfds, readfds, writefds, exceptfds, timeout); + } + + /*nstack select not support timer function and not check nfds so calling dufault select */ + if ((nfds <= 0) + || ((NULL == readfds) && (NULL == writefds) && (NULL == exceptfds))) + { + if ((select_module) && (select_module->default_fun)) + { + return select_module->default_fun (nfds, readfds, writefds, + exceptfds, timeout); + } + else + { + return nsfw_base_select (nfds, readfds, writefds, exceptfds, + timeout); + } + } + + entry = (struct select_entry *) select_alloc (sizeof (struct select_entry)); + if (NULL == entry) + { + errno = ENOMEM; + NSSOC_LOGERR ("select entry alloc failed"); + goto err_return; + } + + /* fix dead-code type Codedex issue */ + /*split select fd to each modules fd and save to entry */ + (void) select_cb_split_by_mod (nfds, readfds, writefds, exceptfds, entry); + + /*if all fd in default module we just calling it */ + if (entry->info.set_num <= 1) + { + + /*adapte linux */ + if ((select_module) + && (entry->info.index == select_module->default_mod)) + { + if (select_module->default_fun) + { + ret = + select_module->default_fun (nfds, readfds, writefds, + exceptfds, timeout); + } + else + { + ret = + nsfw_base_select (nfds, readfds, writefds, exceptfds, + timeout); + } + goto err_return; + } + } + + /*cheching if event ready or not */ + if (FALSE == select_scan (entry)) + { + NSSOC_LOGERR ("select scan failed"); + goto err_return; + } + + if (entry->ready.readyset != 0) + { + goto scan_return; + } + + if ((timeout) && (timeout->tv_sec == 0) && (timeout->tv_usec == 0)) + { + goto scan_return; + } + + if (FALSE == select_add_cb (entry)) + { + errno = ENOMEM; + NSSOC_LOGERR ("select entry add failed"); + goto err_return; + } + + if (NULL == timeout) + { + select_sem_wait (&entry->sem); + } + else + { + u64_t time_cost; + if (nstack_timeval2msec (timeout, &msec)) + { + nstack_set_errno (EINVAL); + goto err_return; + } + time_cost = nstack_sem_timedwait (&entry->sem, msec); + if (time_cost >= msec) + { + timeout->tv_sec = 0; + timeout->tv_usec = 0; + } + else if (time_cost > 0) + { + msec = msec - time_cost; + timeout->tv_sec = msec / 1000; + timeout->tv_usec = (msec % 1000) * 1000; + } + } + + select_rm_cb (entry); + +scan_return: + if (readfds) + { + *readfds = entry->ready.readset; + } + if (writefds) + { + *writefds = entry->ready.writeset; + } + if (exceptfds) + { + *exceptfds = entry->ready.exceptset; + } + + ret = entry->ready.readyset; + if (ret < 0) + { + errno = entry->ready.select_errno; + } + +err_return: + if (entry) + { + select_free ((char *) entry); + } + NSSOC_LOGDBG + ("(nfds=%d,readfds=%p,writefds=%p,exceptfds=%p,timeout=%p),ret=%d errno = %d", + nfds, readfds, writefds, exceptfds, timeout, ret, errno); + return ret; +} + +/* epfd?fd maybe is from kernel or stack-x,should take care */ +int +nstack_epoll_ctl (int epfd, int op, int fd, struct epoll_event *event) +{ + int ret = ns_fail; + struct eventpoll *ep = NULL; + nstack_fd_Inf *epInf; + struct epoll_event ep_event = { 0 }; + struct epitem *epi = NULL; + + nstack_set_tracing_contex (0, 0, fd); + NSSOC_LOGINF ("(epfd=%d, op=%d, fd=%d, event=%p) [Caller]", epfd, op, fd, + event); + if (event) + NSSOC_LOGINF ("event->data.fd=%d,event->events=%u", event->data.fd, + event->events); + + NSTACK_FD_LINUX_CHECK (epfd, epoll_ctl, epInf, (epfd, op, fd, event)); + + nstack_fd_local_lock_info_t *epoll_local_lock = &epInf->local_lock; + LOCK_EPOLL (epfd, epInf, epoll_local_lock); + nstack_fd_local_lock_info_t *local_lock = get_fd_local_lock_info (fd); + LOCK_EPOLL_CTRL (fd, local_lock, epfd, epoll_local_lock); + + if (!NSTACK_IS_FD_EPOLL_SOCKET (epInf) || fd == epfd) /* `man epoll_ctl` tells me to do this check :) */ + { + NSSOC_LOGWAR ("epfd=%d is not a epoll fd [return]", epfd); + errno = EINVAL; + goto err_return; + } + + if (!nstack_is_nstack_sk (fd)) + { + NSSOC_LOGWAR ("epfd=%d ,fd %d is not a supported [return]", epfd, fd); + errno = EBADF; + goto err_return; + } + + nsep_epollInfo_t *epInfo = nsep_get_infoBySock (epfd); + if (NULL == epInfo) + { + NSSOC_LOGWAR ("epInfo of epfd=%d is NULL [return]", epfd); + errno = EINVAL; + goto err_return; + } + + ep = ADDR_SHTOL (epInfo->ep); + if (NULL == ep) + { + NSSOC_LOGWAR ("ep of epfd=%d is NULL [return]", epfd); + errno = EINVAL; + goto err_return; + } + + if (NULL != event) + { + ep_event.data = event->data; + ep_event.events = event->events; + } + else + { + if (op != EPOLL_CTL_DEL) + { + NSSOC_LOGWAR ("events epfd=%d is NULL [return]", epfd); + errno = EFAULT; + goto err_return; + } + } + + sys_arch_lock_with_pid (&ep->sem); + + epi = nsep_find_ep (ep, fd); + switch (op) + { + case EPOLL_CTL_ADD: + if (!epi) + { + ep_event.events |= (EPOLLERR | EPOLLHUP); // Check `man epoll_ctl` if you don't understand , smile :) + common_mem_rwlock_read_lock (get_fork_lock ()); /* to ensure that there is no fd to create and close when fork. added by tongshaojun t00391048 */ + ret = nsep_epctl_add (ep, fd, &ep_event); + common_mem_rwlock_read_unlock (get_fork_lock ()); + } + else + { + NSSOC_LOGWAR ("fd already in eventpoll"); + errno = EEXIST; + ret = -1; + } + break; + case EPOLL_CTL_DEL: + if (epi) + { + common_mem_rwlock_read_lock (get_fork_lock ()); + ret = nsep_epctl_del (ep, epi); + common_mem_rwlock_read_unlock (get_fork_lock ()); + } + else + { + NSSOC_LOGWAR ("fd not registed before"); + errno = ENOENT; + ret = -1; + } + break; + case EPOLL_CTL_MOD: + if (epi) + { + ep_event.events |= (EPOLLERR | EPOLLHUP); // Look up ? + ret = nsep_epctl_mod (ep, nsep_get_infoBySock (fd), epi, &ep_event); + } + else + { + NSSOC_LOGWAR ("fd not registed before"); + errno = ENOENT; + ret = -1; + } + break; + default: + NSSOC_LOGERR ("epfd=%d,fd=%d,opt=%d not supported", epfd, fd, op); + errno = EINVAL; + ret = -1; + } + + sys_sem_s_signal (&ep->sem); + NSSOC_LOGINF ("epfd=%d,op=%d,fd=%d,ret=%d [return]", epfd, op, fd, ret); + +err_return: + UNLOCK_EPOLL_CTRL (fd, local_lock); + UNLOCK_EPOLL (epfd, epoll_local_lock); + return ret; +} + +int +nstack_epoll_create (int size) +{ + nstack_fd_Inf *fdInf = NULL; + struct eventpoll *ep = NULL; + int epfd = -1; + int modInx = 0; + int tfd = 0; + nstack_socket_ops *ops; + int ret = 0; + + nstack_set_tracing_contex (0, 0, -1); + + NSTACK_INIT_CHECK_RET (epoll_create); + + NSSOC_LOGINF ("(size=%d) [Caller]", size); + + if (size <= 0) + { + nstack_set_errno (EINVAL); + NSSOC_LOGERR ("invalid input,param]size=%d [return]", size); + return -1; + } + + /*create a epfd */ + if (nstack_fix_mid_ops ()->pfepoll_create) + { + epfd = nstack_fix_mid_ops ()->pfepoll_create (size); + } + else + { + /*if not surport epfd create, just alloc a fd */ + if (nstack_extern_deal (nstack_get_fix_mid ()).stack_alloc_fd) + { + epfd = nstack_extern_deal (nstack_get_fix_mid ()).stack_alloc_fd (); + } + else + { + nstack_set_errno (ENOSYS); + NSSOC_LOGERR ("not surport epoll create]size=%d [return]", size); + return -1; + } + } + if (!nstack_is_nstack_sk (epfd)) + { + if (epfd >= 0) + { + NSTACK_CAL_FUN (nstack_fix_mid_ops (), close, (epfd), ret); + } + NSSOC_LOGERR ("kernel fd alloced is too larger]kernel_fd=%d [return]", + epfd); + nstack_set_errno (EMFILE); + return -1; + } + + nstack_fd_local_lock_info_t *lock_info = get_fd_local_lock_info (epfd); + LOCK_FOR_EP (lock_info); + fdInf = nstack_lk_fd_alloc_with_kernel (epfd); + if (NULL == fdInf) + { + NSSOC_LOGERR ("create fdInf fail [return]"); + nstack_set_errno (ENOMEM); + NSTACK_CAL_FUN (nstack_fix_mid_ops (), close, (epfd), ret); + UNLOCK_FOR_EP (lock_info); + return -1; + } + + if (nsep_alloc_eventpoll (&ep)) + { + nsep_free_infoWithSock (epfd); + NSSOC_LOGERR ("Alloc eventpoll fail [return]"); + nstack_fd_free_with_kernel (fdInf); + nstack_set_errno (ENOMEM); + UNLOCK_FOR_EP (lock_info); + return -1; + } + + ep->epfd = epfd; + nsep_set_infoEp (epfd, ep); + NSTACK_SET_FD_EPOLL_SOCKET (fdInf); + + /*if stack supply ep_create interface, just call create */ + nstack_each_modOps (modInx, ops) + { + + if (modInx == nstack_get_fix_mid ()) + { + nstack_set_protoFd (fdInf, modInx, epfd); + continue; + } + if (ops->pfepoll_create) + { + tfd = ops->pfepoll_create (size); + nstack_set_protoFd (fdInf, modInx, tfd); + } + } + + NSSOC_LOGINF ("fd=%d [return]", epfd); + set_fd_status_lock_fork (epfd, FD_OPEN); + UNLOCK_FOR_EP (lock_info); + return epfd; +} + +void +nstack_epoll_prewait_proc (int epfd, int *eventflag, int num) +{ + int modInx = 0; + nsep_epollInfo_t *epInfo = NULL; + epInfo = nsep_get_infoBySock (epfd); + if (!epInfo) + { + return; + } + nstack_each_modInx (modInx) + { + if (nstack_extern_deal (modInx).ep_prewait_proc) + { + if (epInfo->protoFD[modInx] < 0) + { + continue; + } + /*if already report event, maybe next time to do this proc */ + if ((eventflag) && (modInx < num) && (eventflag[modInx] != 0)) + { + continue; + } + nstack_extern_deal (modInx).ep_prewait_proc (epInfo->protoFD[modInx]); + } + } + return; +} + +int +nstack_epoll_wait (int epfd, struct epoll_event *events, int maxevents, + int timeout) +{ + nstack_fd_Inf *fdInf = NULL; + nsep_epollInfo_t *epInfo = NULL; + struct eventpoll *ep = NULL; + int eventflag[NSEP_SMOD_MAX]; + int evt = 0; + int ret = 0; + + nstack_set_tracing_contex (0, 0, epfd); + NSTACK_FD_LINUX_CHECK (epfd, epoll_wait, fdInf, + (epfd, events, maxevents, timeout)); + + nstack_fd_local_lock_info_t *local_lock = &fdInf->local_lock; + LOCK_EPOLL (epfd, fdInf, local_lock); + + if (!NSTACK_IS_FD_EPOLL_SOCKET (fdInf)) + { + NSSOC_LOGWAR ("epfd=%d is not a epoll fd, return -1", epfd); + errno = EINVAL; + UNLOCK_EPOLL (epfd, local_lock); + return -1; + } + + /* check input paramter's validity */ + if (NULL == events) + { + NSSOC_LOGWAR ("events is NULL, return -1 "); + errno = EINVAL; + UNLOCK_EPOLL (epfd, local_lock); + return -1; + } + + epInfo = nsep_get_infoBySock (epfd); + if (NULL == epInfo) + { + NSSOC_LOGWAR ("epInfo is NULL]epinfo=%p,epfd=%d", epInfo, epfd); + errno = EINVAL; + UNLOCK_EPOLL (epfd, local_lock); + return -1; + } + + ep = ADDR_SHTOL (epInfo->ep); + if (NULL == ep) + { + NSSOC_LOGWAR ("fdInf->ep is NULL, return -1,epinfo=%p,epfd=%d", epInfo, + epfd); + errno = EINVAL; + UNLOCK_EPOLL (epfd, local_lock); + return -1; + } + + if (maxevents <= 0) + { + NSSOC_LOGWAR ("maxevent less than zero maxevents=%d, return -1 ", + maxevents); + errno = EINVAL; + UNLOCK_EPOLL (epfd, local_lock); + return -1; + } + + /** + * For linux epoll + * Case 1: event is already there, means ks_ep_thread already reported, and epfd not in epoll. + * Case 2: event is not there, so we need to add epfd to ks_ep_thread + * Update : only try to add epfd to ks_ep_thread once, avoid ks_ep_thread reporting the same event again after app has got the event! + */ + MEMSET_S (&eventflag[0], sizeof (eventflag), 0, sizeof (eventflag)); + evt = nsep_ep_poll (ep, events, maxevents, &eventflag[0], NSEP_SMOD_MAX); + if (evt) + { + NSSOC_LOGDBG ("Got event]epfd=%d,maxevents=%d,ret=%d", epfd, maxevents, + evt); + nstack_epoll_prewait_proc (epfd, &eventflag[0], NSEP_SMOD_MAX); + goto out; + } + nstack_epoll_prewait_proc (epfd, NULL, 0); + do + { + if (0 == timeout) + { + goto out; + } + else if (timeout < 0) + { + ret = sem_wait (&ep->waitSem); + /* when sem_wait return -1, epoll_wait should also return sem_wait's return value and errno */ + if (ret < 0) + { + /* Change sem_wait EINTR log to WAR level */ + if (errno == EINTR) + { + NSSOC_LOGWAR ("sem_wait return -1]errno=%d", errno); + } + else + { + NSSOC_LOGERR ("sem_wait return -1]errno=%d", errno); + } + + evt = ret; + goto out; + } + } + else + { + ret = + nstack_epoll_sem_timedwait (&ep->waitSem, (u64_t) timeout, + epInfo->sleepTime); + } + + if (ret) + { + goto out; + } + + evt = nsep_ep_poll (ep, events, maxevents, NULL, 0); + if (evt) + { + NSSOC_LOGDBG ("Got event]epfd=%d,maxevents=%d,ret=%d", epfd, + maxevents, evt); + goto out; + } + } + while (1); + +out: + UNLOCK_EPOLL (epfd, local_lock); + return evt; +} + +pid_t +nstack_fork (void) +{ + pid_t pid; + pid_t parent_pid = sys_get_hostpid_from_file (getpid ()); + + nstack_set_tracing_contex (0, 0, -1); + common_mem_rwlock_write_lock (get_fork_lock ()); + if (NSTACK_MODULE_SUCCESS == g_nStackInfo.fwInited) + { + nstack_fork_init_parent (parent_pid); + dmm_spinlock_lock_with_pid (nstack_get_fork_share_lock (), parent_pid); + pid = nsfw_base_fork (); + if (pid == 0) + { + /* when fork, the child process need relese the lock in glog */ + nstack_log_lock_release (); + nstack_fork_init_child (parent_pid); + (void) nstack_for_epoll_init (); + dmm_spinlock_lock_with_pid (nstack_get_fork_share_lock (), + get_sys_pid ()); + nsep_fork_child_proc (parent_pid); + common_mem_spinlock_unlock (nstack_get_fork_share_lock ()); + } + else if (pid > 0) + { + pid_t child_pid = get_hostpid_from_file (pid); + nsep_fork_parent_proc (parent_pid, child_pid); + common_mem_spinlock_unlock (nstack_get_fork_share_lock ()); + sys_sleep_ns (0, 10000000); /* wait child add pid for netconn */ + } + else + { + NSSOC_LOGERR ("fork failed]parent_pid=%d", parent_pid); + common_mem_spinlock_unlock (nstack_get_fork_share_lock ()); + } + } + else + { + pid = nsfw_base_fork (); + if (pid == 0) + { + updata_sys_pid (); + } + NSSOC_LOGERR ("g_nStackInfo has not initialized]parent_pid=%d, pid=%d", + parent_pid, pid); + } + + common_mem_rwlock_write_unlock (get_fork_lock ()); + return pid; +} diff --git a/src/nSocket/nstack/nstack_socket.h b/src/nSocket/nstack/nstack_socket.h new file mode 100644 index 0000000..ff05099 --- /dev/null +++ b/src/nSocket/nstack/nstack_socket.h @@ -0,0 +1,231 @@ +/* +* +* 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 __NSTACK_SOCKET_H__ +#define __NSTACK_SOCKET_H__ +#include +#include +#include + +#undef NSTACK_MK_DECL +#define NSTACK_MK_DECL(ret, fn, args) extern ret nstack_##fn args +#include "declare_syscalls.h" + +int release_fd (int fd, nstack_fd_local_lock_info_t * local_lock); +int nstack_posix_api_init (); +int nstack_close (int fd); +int nstack_socket (int domain, int itype, int protocol); + +#define NSTACK_EPOLL_FD_CHECK_RET_UNLOCK(fdVal, fun, inf, err, local_lock, unlock) \ + if ((NULL == inf) || ((inf)->attr & NSTACK_FD_ATTR_EPOLL_SOCKET)) \ + { \ + nstack_set_errno(err); \ + NSSOC_LOGERR("nstack [%s] call, fd=0x%x is epoll fd return fail errno=%d [return]", #fun, fdVal, err); \ + unlock(fdVal, local_lock);\ + return -1;\ + } + +#define NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_COMMON(fdVal, fun, inf, err, local_lock) \ + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK(fdVal, fun, inf, err, local_lock, UNLOCK_COMMON) + +#define LOCK_RECV(fd, fd_inf, local_lock)\ + LOCK_BASE_WITHOUT_KERNEL(fd, fd_inf, local_lock) + +#define UNLOCK_RECV(fd, local_lock) \ + UNLOCK_BASE(fd, local_lock) + +#define NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_RECV(fdVal, fun, inf, err, local_lock) \ + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK(fdVal, fun, inf, err, local_lock, UNLOCK_RECV) + +#define LOCK_SEND(fd, fd_inf, local_lock) \ + INC_FD_REF(fd, fd_inf, local_lock) + +static inline void +UNLOCK_SEND (int fd, nstack_fd_local_lock_info_t * local_lock) +{ + if ((NULL != local_lock) && atomic_dec (&local_lock->fd_ref) == 0) + { + release_fd (fd, local_lock); + } +} + +#define NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_SEND(fdVal, fun, inf, err, local_lock) \ + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK(fdVal, fun, inf, err, local_lock, UNLOCK_SEND) + +#define LOCK_CONNECT(fd, fd_inf, local_lock) \ + LOCK_BASE(fd, fd_inf, local_lock) + +#define UNLOCK_CONNECT(fd, local_lock) \ + UNLOCK_BASE(fd, local_lock) + +#define NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_CONNECT(fdVal, fun, inf, err, local_lock) \ + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK(fdVal, fun, inf, err, local_lock, UNLOCK_CONNECT) + +#define LOCK_ACCEPT(fd, fd_inf, local_lock) \ + LOCK_BASE(fd, fd_inf, local_lock) + +#define UNLOCK_ACCEPT(fd, local_lock) \ + UNLOCK_BASE(fd, local_lock) + +#define NSTACK_EPOLL_FD_CHECK_RET_UNLOCK_ACCEPT(fdVal, fun, inf, err, local_lock) \ + NSTACK_EPOLL_FD_CHECK_RET_UNLOCK(fdVal, fun, inf, err, local_lock, UNLOCK_ACCEPT) + +#define LOCK_EPOLL(fd, fd_inf, local_lock) INC_FD_REF(fd, fd_inf, local_lock) + +static inline void +UNLOCK_EPOLL (int fd, nstack_fd_local_lock_info_t * local_lock) +{ + if ((NULL != local_lock) && atomic_dec (&local_lock->fd_ref) == 0) + { + release_fd (fd, local_lock); + } +} + +#define LOCK_EPOLL_CTRL(fd_val, local_lock, epoll_fd, epoll_local_lock){\ + if (local_lock)\ + {\ + atomic_inc(&local_lock->fd_ref);\ + common_mem_spinlock_lock(&local_lock->close_lock);\ + nstack_fd_Inf* fd_inf = nstack_getValidInf(fd_val);\ + if (fd_inf)\ + {\ + if (local_lock->fd_status != FD_OPEN)\ + {\ + NSSOC_LOGWAR("fd %d is not open [return]", fd_val);\ + nstack_set_errno(EBADF);\ + common_mem_spinlock_unlock(&local_lock->close_lock);\ + if(atomic_dec(&local_lock->fd_ref)==0){ \ + release_fd(fd_val, local_lock);\ + }\ + UNLOCK_EPOLL(epoll_fd, epoll_local_lock);\ + return -1;\ + }\ + }\ + }\ +} + +static inline void +UNLOCK_EPOLL_CTRL (int fd, nstack_fd_local_lock_info_t * local_lock) +{ + if (local_lock) + { + common_mem_spinlock_unlock (&local_lock->close_lock); + if (atomic_dec (&local_lock->fd_ref) == 0) + { + release_fd (fd, local_lock); + } + } +} + +#ifndef FOR_NSTACK_UT +#define INC_FD_REF(fd, fd_inf, local_lock){ \ + if (local_lock)\ + {\ + atomic_inc(&local_lock->fd_ref);\ + if (local_lock->fd_status != FD_OPEN)\ + {\ + nstack_set_errno(EBADF);\ + NSSOC_LOGERR("nstack call, fd_status=%d [return]", local_lock->fd_status); \ + if(atomic_dec(&local_lock->fd_ref) == 0){ \ + release_fd(fd, local_lock);\ + }\ + return -1;\ + }\ + } \ +} +#else +static inline int +ut_inc_fd_ref (int fd, nStack_info_t * fdInf, + nstack_fd_local_lock_info_t * local_lock) +{ + if (local_lock) + { + atomic_inc (&local_lock->fd_ref); + if (local_lock->fd_status != FD_OPEN) + { + nstack_set_errno (EBADF); + NSSOC_LOGERR ("nstack call, fd_status=%d [return]", + local_lock->fd_status); + if (atomic_dec (&local_lock->fd_ref) == 0) + { + release_fd (fd, local_lock); + } + return -1; + } + } + return 0; +} + +#define INC_FD_REF(fd, fd_inf, local_lock){\ + if(ut_inc_fd_ref(fd, fd_inf, local_lock) < 0)\ + return -1;\ +} +#endif + +#define LOCK_BASE(fd, fd_inf, local_lock){\ + INC_FD_REF(fd, fd_inf, local_lock);\ +} + +/* if is kernel fd, don't need to lock */ +#define LOCK_BASE_WITHOUT_KERNEL(fd, fd_inf, local_lock){\ + INC_FD_REF(fd, fd_inf, local_lock);\ +} + +static inline void +UNLOCK_BASE (int fd, nstack_fd_local_lock_info_t * local_lock) +{ + if ((NULL != local_lock) && (atomic_dec (&local_lock->fd_ref) == 0)) + { + release_fd (fd, local_lock); + } +} + +#define LOCK_COMMON(fd, fd_inf, local_lock) \ + LOCK_BASE(fd, fd_inf, local_lock) + +#define UNLOCK_COMMON(fd, local_lock) \ + UNLOCK_BASE(fd, local_lock) + +#define LOCK_CLOSE(local_lock){\ + if (local_lock)\ + {\ + common_mem_spinlock_lock(&local_lock->close_lock);\ + }\ +} + +static inline void +UNLOCK_CLOSE (nstack_fd_local_lock_info_t * local_lock) +{ + if (local_lock) + { + common_mem_spinlock_unlock (&local_lock->close_lock); + } +} + +#define LOCK_FOR_EP(local_lock) LOCK_CLOSE(local_lock) + +#define UNLOCK_FOR_EP(local_lock) UNLOCK_CLOSE(local_lock) + +#define NSTACK_INIT_CHECK_RET(fun) \ + if (nstack_fw_init()) { \ + NSSOC_LOGERR("nstack %s call, but initial not finished yet [return]", #fun); \ + nstack_set_errno(ENOSYS); \ + return -1; \ + } + +#define NSTACK_MODULE_ERROR_SET(Index) + +#endif /* __NSTACK_SOCKET_H__ */ diff --git a/src/nSocket/nstack_rd/nstack_rd.c b/src/nSocket/nstack_rd/nstack_rd.c new file mode 100644 index 0000000..ee598ad --- /dev/null +++ b/src/nSocket/nstack_rd/nstack_rd.c @@ -0,0 +1,386 @@ +/* +* +* 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 +#include +#include +#include +#include "nstack_rd.h" +#include "nstack_rd_init.h" +#include "nstack_rd_priv.h" +#include "nstack_rd_ip.h" +#include "nstack_rd_proto.h" +#include "nstack_log.h" +#include "nstack_info_parse.h" +#include "nstack_securec.h" + +typedef struct __rd_data_defaut_ip +{ + char ip[RD_IP_STR_MAX_LEN]; + char planename[RD_PLANE_NAMELEN]; + int masklent; +} rd_data_defaut_ip; + +typedef struct __rd_data_defaut_protocol +{ + unsigned int proto_type; + char planename[RD_PLANE_NAMELEN]; +} rd_data_defaut_protocol; + +extern rd_stack_plane_map g_nstack_plane_info[]; +extern int g_rd_map_num; + +rd_data_proc g_rd_cpy[RD_DATA_TYPE_MAX] = { + { + nstack_rd_ipdata_cpy, + nstack_rd_ip_item_insert, + nstack_rd_ip_item_age, + nstack_rd_ip_item_find, + nstack_rd_ip_spec, + nstack_rd_ip_default, + }, + { + nstack_rd_proto_cpy, + nstack_rd_proto_item_insert, + nstack_rd_proto_item_age, + nstack_rd_proto_item_find, + nstack_rd_proto_spec, + nstack_rd_proto_default, + }, +}; + +rd_data_defaut_ip g_defualt_ip_config[] = { + {{"127.0.0.1"}, {RD_LINUX_PLANENAME}, 32}, + {{"0.0.0.0"}, {RD_LINUX_PLANENAME}, 32}, +}; + +rd_data_defaut_protocol g_defualt_protcol[] = { + {0xf001, {RD_STACKX_PLANENAME}}, +}; + +/***************************************************************************** +* Prototype : nstack_rd_get_stackid +* Description : choose the stack by key, type is the most important +* Input : nstack_rd_key* pkey +* int *stackid +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nstack_rd_get_stackid (nstack_rd_key * pkey, int *stackid) +{ + int type = 0; + int ret = NSTACK_RD_SUCCESS; + rd_data_item item; + if ((!pkey) || (!stackid) || (pkey->type >= RD_DATA_TYPE_MAX)) + { + NSSOC_LOGERR ("input get stackid fail]addr=%p,stackid=%p,addr->type=%d", + pkey, stackid, !pkey ? RD_DATA_TYPE_MAX : pkey->type); + return NSTACK_RD_FAIL; + } + int retVal = MEMSET_S (&item, sizeof (item), 0, sizeof (item)); + if (EOK != retVal) + { + NSSOC_LOGERR ("MEMSET_S failed]retVal=%d", retVal); + return NSTACK_RD_FAIL; + } + type = pkey->type; + + /*specfic key find, for ip example: stack-x was chose if the key is multicast ip */ + if (g_rd_cpy[type].rd_item_spec) + { + ret = g_rd_cpy[type].rd_item_spec ((void *) pkey); + if (ret >= 0) + { + *stackid = ret; + return NSTACK_RD_SUCCESS; + } + } + + /*search the list */ + ret = + g_rd_cpy[type].rd_item_find (NSTACK_RD_LIST (type), (void *) pkey, &item); + if (NSTACK_RD_SUCCESS == ret) + { + NSSOC_LOGDBG ("item type=%d stackid=%d was found", pkey->type, + item.stack_id); + *stackid = item.stack_id; + return NSTACK_RD_SUCCESS; + } + if (g_rd_cpy[type].rd_item_defualt) + { + *stackid = g_rd_cpy[type].rd_item_defualt ((void *) pkey); + } + else + { + *stackid = -1; + } + NSSOC_LOGINF ("item type=%d was not found, return default=%d", pkey->type, + *stackid); + return NSTACK_RD_SUCCESS; +} + +/***************************************************************************** +* Prototype : nstack_rd_sys_default +* Description : sys defualt rd info, +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +******************************************************************************/ +void +nstack_rd_sys_default () +{ + rd_data_item item; + rd_data_defaut_ip *pdata = NULL; + rd_data_defaut_protocol *pprotodata = NULL; + int icnt = 0, iindex = 0; + + /*get the ip defualt route */ + for (icnt = 0; + icnt < sizeof (g_defualt_ip_config) / sizeof (rd_data_defaut_ip); + icnt++) + { + pdata = &g_defualt_ip_config[icnt]; + for (iindex = 0; iindex < g_rd_map_num; iindex++) + { + if (0 == + strcmp (g_nstack_plane_info[iindex].planename, + pdata->planename)) + { + item.stack_id = g_nstack_plane_info[iindex].stackid; + break; + } + } + if (iindex >= g_rd_map_num) + { + NSSOC_LOGINF + ("default plane name:%s was not fount, ip:%s msklen:%d was dropped", + pdata->planename, pdata->ip, pdata->masklent); + continue; + } + item.type = RD_DATA_TYPE_IP; + item.ipdata.addr = ntohl (inet_addr (pdata->ip)); + item.ipdata.masklen = pdata->masklent; + item.ipdata.resev[0] = 0; + item.ipdata.resev[1] = 0; + item.agetime = NSTACK_RD_AGETIME_MAX; + /*insert to the list */ + g_rd_cpy[RD_DATA_TYPE_IP].rd_item_inset (NSTACK_RD_LIST + (RD_DATA_TYPE_IP), &item); + } + + /*get the protocol defualt route */ + (void) MEMSET_S (&item, sizeof (item), 0, sizeof (item)); + for (icnt = 0; + icnt < sizeof (g_defualt_protcol) / sizeof (rd_data_defaut_ip); icnt++) + { + pprotodata = &g_defualt_protcol[icnt]; + for (iindex = 0; iindex < g_rd_map_num; iindex++) + { + if (0 == + strcmp (g_nstack_plane_info[iindex].planename, + pprotodata->planename)) + { + item.stack_id = g_nstack_plane_info[iindex].stackid; + break; + } + } + if (iindex >= g_rd_map_num) + { + NSSOC_LOGINF + ("default plane name:%s was not fount, protocoltype:%d was dropped", + pprotodata->planename, pprotodata->proto_type); + continue; + } + item.type = RD_DATA_TYPE_PROTO; + item.proto_type = pprotodata->proto_type; + /*insert to the list */ + g_rd_cpy[RD_DATA_TYPE_PROTO].rd_item_inset (NSTACK_RD_LIST + (RD_DATA_TYPE_PROTO), + &item); + } + return; +} + +/***************************************************************************** +* Prototype : nstack_rd_save +* Description : save the rd data +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +void +nstack_rd_save (rd_route_data * rd_data, int num) +{ + int icnt = 0; + int iindex = 0; + rd_data_item item; + rd_data_type type = RD_DATA_TYPE_MAX; + + int retVal = MEMSET_S (&item, sizeof (item), 0, sizeof (item)); + if (EOK != retVal) + { + NSSOC_LOGERR ("MEMSET_S failed]retVal=%d", retVal); + return; + } + + for (iindex = 0; iindex < num; iindex++) + { + if (rd_data[iindex].type >= RD_DATA_TYPE_MAX) + { + NSSOC_LOGERR ("rd data type=%d unkown", rd_data[iindex].type); + continue; + } + + type = rd_data[iindex].type; + + if (NSTACK_RD_SUCCESS == + g_rd_cpy[type].rd_item_cpy ((void *) &item, + (void *) &rd_data[iindex])) + { + item.agetime = NSTACK_RD_AGETIME_MAX; + for (icnt = 0; icnt < g_rd_map_num; icnt++) + { + if (0 == + strcmp (g_nstack_plane_info[icnt].planename, + rd_data[iindex].stack_name)) + { + item.stack_id = g_nstack_plane_info[icnt].stackid; + break; + } + } + if (icnt >= g_rd_map_num) + { + NSSOC_LOGINF + ("plane name:%s was not fount, protocoltype:%d was dropped", + rd_data[iindex].stack_name); + continue; + } + /*insert to the list */ + g_rd_cpy[type].rd_item_inset (NSTACK_RD_LIST (type), &item); + continue; + } + + NSSOC_LOGERR ("rd data type=%d cpy fail", rd_data[iindex].type); + } + return; +} + +/***************************************************************************** +* Prototype : nstack_rd_data_get +* Description : rd data get, +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nstack_rd_data_get (nstack_get_route_data pfun) +{ + rd_route_data *rd_data = NULL; + int iret = NSTACK_RD_FAIL; + int inum = 0; + + /*get rd config */ + if (pfun && (NSTACK_RD_SUCCESS == pfun (&rd_data, &inum))) + { + if (inum > 0) + { + nstack_rd_save (rd_data, inum); + iret = NSTACK_RD_SUCCESS; + } + else + { + NSSOC_LOGDBG ("no rd data got"); + } + if (rd_data) + { + free (rd_data); + rd_data = NULL; + } + } + else + { + NSSOC_LOGERR ("nstack rd sys rd info fail"); + } + return iret; +} + +/***************************************************************************** +* Prototype : nstack_rd_sys +* Description : sys rd data from rd table, +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nstack_rd_sys () +{ + int iret = NSTACK_RD_FAIL; + int icnt = 0; + if (!g_rd_local_data) + { + NSSOC_LOGERR ("rd have not been inited"); + return NSTACK_RD_FAIL; + } + + /*insert defualt rd info */ + nstack_rd_sys_default (); + + /*get from config file */ + for (icnt = 0; icnt < g_rd_local_data->fun_num; icnt++) + { + if (NSTACK_RD_SUCCESS == + nstack_rd_data_get (g_rd_local_data->sys_fun[icnt])) + { + iret = NSTACK_RD_SUCCESS; + } + } + + /*age after sys */ + nstack_rd_age (); + return iret; +} + +/***************************************************************************** +* Prototype : nstack_rd_age +* Description : delete all rd item from the list that not been add again + for at least one time +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nstack_rd_age () +{ + int icnt = 0; + for (icnt = 0; icnt < RD_DATA_TYPE_MAX; icnt++) + { + (void) g_rd_cpy[icnt].rd_item_age (NSTACK_RD_LIST (icnt)); + } + return NSTACK_RD_SUCCESS; +} diff --git a/src/nSocket/nstack_rd/nstack_rd_init.c b/src/nSocket/nstack_rd/nstack_rd_init.c new file mode 100644 index 0000000..3025e88 --- /dev/null +++ b/src/nSocket/nstack_rd/nstack_rd_init.c @@ -0,0 +1,202 @@ +/* +* +* 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 +#include "nstack_rd.h" +#include "nstack_rd_data.h" +#include "nstack_rd_init.h" +#include "nstack_rd_priv.h" +#include "nstack_log.h" +#include "nstack_securec.h" + +#define NSTACK_RD_ERR_CHECK_GOTO(ret, desc, lab) \ +if (NSTACK_RD_SUCCESS != (ret))\ +{ \ + NSSOC_LOGERR("%s fail, return:%d", desc, ret); \ + goto lab; \ +} + +#define NSTACK_RD_POINT_CHECK_GOTO(ptr, desc, lab) \ +if (!ptr)\ +{ \ + NSSOC_LOGERR("%s fail", desc); \ + goto lab; \ +} + +/* *INDENT-OFF* */ +rd_stack_plane_map g_nstack_plane_info[] = { + {{RD_LINUX_NAME}, {RD_LINUX_PLANENAME}, -1}, + {{RD_STACKX_NAME}, {RD_STACKX_PLANENAME}, -1}, +}; +/* *INDENT-ON* */ + +int g_rd_map_num = sizeof (g_nstack_plane_info) / sizeof (rd_stack_plane_map); + +rd_local_data *g_rd_local_data = NULL; + +/***************************************************************************** +* Prototype : nstack_rd_init +* Description : nstack rd init +* Input : nstack_stack_info *pstack +* int num +* nstack_get_route_data pfun +* Output : None +* Return Value : int +* Calls : +* Called By : +* pstack : 1. priority 0: when router not fund, the first will be chose +* 2. if have many same 0 priority, fist input will be chose, +* 3. if none 0 priority, the last input will be choose +*****************************************************************************/ +int +nstack_rd_init (nstack_stack_info * pstack, int num, + nstack_get_route_data * pfun, int fun_num) +{ + int icnt = 0; + int itemp = 0; + int hindex = 0; + int tindex = num - 1; + int iindex = 0; + int ret = NSTACK_RD_SUCCESS; + nstack_rd_stack_info *ptemstack = NULL; + + if ((!pstack) || (!pfun)) + { + NSSOC_LOGERR ("input err pstack:%p, pfun:%p", pstack, pfun); + return NSTACK_RD_FAIL; + } + g_rd_local_data = (rd_local_data *) malloc (sizeof (rd_local_data)); + if (!g_rd_local_data) + { + NSSOC_LOGERR ("g_rd_local_data alloc fail"); + return NSTACK_RD_FAIL; + } + + if (EOK != + MEMSET_S ((void *) g_rd_local_data, sizeof (rd_local_data), 0, + sizeof (rd_local_data))) + { + NSSOC_LOGERR ("MEMSET_S fail"); + goto ERR; + } + for (icnt = 0; icnt < fun_num; icnt++) + { + g_rd_local_data->sys_fun[icnt] = pfun[icnt]; + } + g_rd_local_data->fun_num = fun_num; + ptemstack = + (nstack_rd_stack_info *) malloc (sizeof (nstack_rd_stack_info) * num); + NSTACK_RD_POINT_CHECK_GOTO (ptemstack, "rd stack info malloc fail", ERR); + + /*save stack info in priority order */ + for (icnt = 0; icnt < num; icnt++) + { + if (0 == pstack[icnt].priority) + { + iindex = hindex; + hindex++; + } + else + { + iindex = tindex; + tindex--; + } + + /* modify destMax from RD_PLANE_NAMELEN to STACK_NAME_MAX */ + ret = + STRCPY_S (ptemstack[iindex].stack.stackname, STACK_NAME_MAX, + pstack[icnt].name); + if (ret != EOK) + { + NSSOC_LOGERR ("STRCPY_S failed"); + goto ERR; + } + + for (itemp = 0; itemp < g_rd_map_num; itemp++) + { + if (0 == + strcmp (pstack[icnt].name, + g_nstack_plane_info[itemp].stackname)) + { + ret = + STRCPY_S (ptemstack[iindex].stack.planename, RD_PLANE_NAMELEN, + g_nstack_plane_info[itemp].planename); + g_nstack_plane_info[itemp].stackid = pstack[icnt].stack_id; + NSTACK_RD_ERR_CHECK_GOTO (ret, "plane name copy fail", ERR); + break; + } + } + + if (itemp >= g_rd_map_num) + { + NSSOC_LOGERR ("rd route info not found"); + goto ERR; + } + ptemstack[iindex].priority = pstack[icnt].priority; + ptemstack[iindex].stack_id = pstack[icnt].stack_id; + NSSOC_LOGDBG + ("nstack rd init]stackname=%s,planename=%s,priority=%d,stackid=%d was added", + ptemstack[iindex].stack.stackname, ptemstack[iindex].stack.planename, + ptemstack[iindex].priority, ptemstack[iindex].stack_id); + } + + g_rd_local_data->pstack_info = ptemstack; + g_rd_local_data->stack_num = num; + + for (icnt = 0; icnt < RD_DATA_TYPE_MAX; icnt++) + { + INIT_HLIST_HEAD (&(g_rd_local_data->route_list[icnt].headlist)); + } + return NSTACK_RD_SUCCESS; + +ERR: + if (g_rd_local_data) + { + free (g_rd_local_data); + g_rd_local_data = NULL; + } + if (ptemstack) + { + free (ptemstack); + } + return NSTACK_RD_FAIL; +} + +/***************************************************************************** +* Prototype : nstack_get_stackid_byname +* Description : get stack ip by stack name +* Input : char *name +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nstack_get_stackid_byname (char *name) +{ + int stacknum = g_rd_local_data->stack_num; + int iindex = 0; + nstack_rd_stack_info *pstack = NULL; + for (iindex = 0; iindex < stacknum; iindex++) + { + pstack = &(g_rd_local_data->pstack_info[iindex]); + if (0 == strcmp (pstack->stack.stackname, name)) + { + return pstack->stack_id; + } + } + return -1; +} diff --git a/src/nSocket/nstack_rd/nstack_rd_ip.c b/src/nSocket/nstack_rd/nstack_rd_ip.c new file mode 100644 index 0000000..bcbe731 --- /dev/null +++ b/src/nSocket/nstack_rd/nstack_rd_ip.c @@ -0,0 +1,264 @@ +/* +* +* 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 +#include +#include "nstack_rd_data.h" +#include "nstack_rd.h" +#include "nstack_rd_init.h" +#include "nstack_rd_priv.h" +#include "nstack_rd_ip.h" +#include "nstack_log.h" +#include "nstack_securec.h" + +#include "nstack_ip_addr.h" + +#define NSTACK_IP_MLSTACKID RD_STACKX_NAME + +#define PP_HTONL(x) ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) + +#define rd_ismulticast(addr)(((unsigned int)(addr) & 0xf0000000UL) == 0xe0000000UL) + +int g_multi_stackid = -1; + +/*copy rd data*/ +int +nstack_rd_ipdata_cpy (void *destdata, void *srcdata) +{ + rd_data_item *pitem = (rd_data_item *) destdata; + rd_route_data *pdata = (rd_route_data *) srcdata; + + pitem->type = pdata->type; + pitem->ipdata.addr = pdata->ipdata.addr; + pitem->ipdata.masklen = pdata->ipdata.masklen; + pitem->ipdata.resev[0] = pdata->ipdata.resev[0]; + pitem->ipdata.resev[1] = pdata->ipdata.resev[1]; + return NSTACK_RD_SUCCESS; +} + +/* + * Add an ip segment to the list and sort it in descending order of ip mask length + * If the list already exists in the same list of ip side, then stack_id update + *ip is local byteorder + */ +int +nstack_rd_ip_item_insert (nstack_rd_list * hlist, void *rditem) +{ + nstack_rd_node *pdatanode = NULL; + nstack_rd_node *tempdata = NULL; + struct hlist_node *tempnode = NULL; + struct hlist_node *tem = NULL; + unsigned int ip_addr = 0; + unsigned int ip_masklen = 0; + unsigned int ip_maskv = MASK_V (ip_addr, ip_masklen); + unsigned int tempip_addr = 0; + unsigned int tempip_masklen = 0; + rd_data_item *pitem = (rd_data_item *) rditem; + + ip_masklen = pitem->ipdata.masklen; + NSSOC_LOGDBG ("stackid:%d, ipaddr:%u.%u.%u.%u masklen:0x%x was inserted", + pitem->stack_id, ip4_addr4_16 (&pitem->ipdata.addr), + ip4_addr3_16 (&pitem->ipdata.addr), + ip4_addr2_16 (&pitem->ipdata.addr), + ip4_addr1_16 (&pitem->ipdata.addr), pitem->ipdata.masklen); + + pdatanode = (nstack_rd_node *) malloc (sizeof (nstack_rd_node)); + if (!pdatanode) + { + NSSOC_LOGERR ("nstack rd item malloc fail"); + return NSTACK_RD_FAIL; + } + int retVal = + MEMSET_S (pdatanode, sizeof (nstack_rd_node), 0, sizeof (nstack_rd_node)); + if (EOK != retVal) + { + NSSOC_LOGERR ("MEMSET_S failed]retVal=%d", retVal); + free (pdatanode); + return NSTACK_RD_FAIL; + } + INIT_HLIST_NODE (&pdatanode->rdnode); + NSTACK_RD_IP_ITEM_COPY (&(pdatanode->item), pitem); + + if (hlist_empty (&(hlist->headlist))) + { + hlist_add_head (&(pdatanode->rdnode), &(hlist->headlist)); + return NSTACK_RD_SUCCESS; + } + hlist_for_each_entry (tempdata, tempnode, &(hlist->headlist), rdnode) + { + tem = tempnode; + tempip_addr = tempdata->item.ipdata.addr; + tempip_masklen = tempdata->item.ipdata.masklen; + if (ip_masklen < tempip_masklen) + { + continue; + } + + /*if already exist, just return success */ + if (ip_maskv == MASK_V (tempip_addr, tempip_masklen)) + { + NSSOC_LOGDBG + ("insert ip:%u.%u.%u.%u, mask:0x%x, stack_id:%d, exist orgid:%d", + ip4_addr4_16 (&pitem->ipdata.addr), + ip4_addr3_16 (&pitem->ipdata.addr), + ip4_addr2_16 (&pitem->ipdata.addr), + ip4_addr1_16 (&pitem->ipdata.addr), pitem->ipdata.masklen, + pitem->stack_id, tempdata->item.stack_id); + + tempdata->item.stack_id = pitem->stack_id; + tempdata->item.agetime = NSTACK_RD_AGETIME_MAX; + free (pdatanode); + return NSTACK_RD_SUCCESS; + } + hlist_add_before (&(pdatanode->rdnode), tempnode); + return NSTACK_RD_SUCCESS; + } + hlist_add_after (tem, &(pdatanode->rdnode)); + return NSTACK_RD_SUCCESS; +} + +/* + *find stackid by ip + *input ip must netorder + */ +int +nstack_rd_ip_item_find (nstack_rd_list * hlist, void *rdkey, void *outitem) +{ + struct hlist_node *tempnode = NULL; + nstack_rd_node *tempdata = NULL; + unsigned int tempip_addr = 0; + unsigned int tempip_masklen = 0; + nstack_rd_key *key = (nstack_rd_key *) rdkey; + rd_data_item *pitem = (rd_data_item *) outitem; + unsigned int ip_addr = 0; + /*need to convert to local order */ + ip_addr = ntohl (key->ip_addr); + + hlist_for_each_entry (tempdata, tempnode, &(hlist->headlist), rdnode) + { + tempip_addr = tempdata->item.ipdata.addr; + tempip_masklen = tempdata->item.ipdata.masklen; + /*if already exist, just return success */ + if (MASK_V (ip_addr, tempip_masklen) == + MASK_V (tempip_addr, tempip_masklen)) + { + NSTACK_RD_IP_ITEM_COPY (pitem, &(tempdata->item)); + return NSTACK_RD_SUCCESS; + } + } + + NSSOC_LOGDBG ("ip=%u.%u.%u.%u item not found", ip4_addr4_16 (&ip_addr), + ip4_addr3_16 (&ip_addr), + ip4_addr2_16 (&ip_addr), ip4_addr1_16 (&ip_addr)); + + return NSTACK_RD_FAIL; +} + +/***************************************************************************** +* Prototype : nstack_rd_ip_item_age +* Description : delete the ip item that have not been add again for one time +* Input : nstack_rd_list *hlist +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nstack_rd_ip_item_age (nstack_rd_list * hlist) +{ + struct hlist_node *tempnode = NULL; + nstack_rd_node *tempdata = NULL; + nstack_rd_node *prevdata = NULL; + struct hlist_node *prevnode = NULL; + NSSOC_LOGINF ("nstack rd ip age begin"); + hlist_for_each_entry (tempdata, tempnode, &(hlist->headlist), rdnode) + { + /*if agetime equal 0, remove it */ + if (tempdata->item.agetime <= 0) + { + if (prevdata) + { + NSSOC_LOGDBG + ("stackid:%d, addrip:%u.%u.%u.%u, masklen:0x%x was aged", + tempdata->item.stack_id, + ip4_addr4_16 (&tempdata->item.ipdata.addr), + ip4_addr3_16 (&tempdata->item.ipdata.addr), + ip4_addr2_16 (&tempdata->item.ipdata.addr), + ip4_addr1_16 (&tempdata->item.ipdata.addr), + tempdata->item.ipdata.masklen); + + hlist_del_init (prevnode); + free (prevdata); + } + prevdata = tempdata; + prevnode = tempnode; + } + else + { + tempdata->item.agetime--; + } + } + if (prevdata) + { + if (tempdata) + { + NSSOC_LOGDBG + ("stackid:%d, addrip:%u.%u.%u.%u, masklen:0x%x was last aged", + tempdata->item.stack_id, + ip4_addr4_16 (&tempdata->item.ipdata.addr), + ip4_addr3_16 (&tempdata->item.ipdata.addr), + ip4_addr2_16 (&tempdata->item.ipdata.addr), + ip4_addr1_16 (&tempdata->item.ipdata.addr), + tempdata->item.ipdata.masklen); + } + hlist_del_init (prevnode); + free (prevdata); + } + NSSOC_LOGINF ("nstack rd ip age end"); + return NSTACK_RD_SUCCESS; +} + +/* + *find stackid by spec ip(multicast ip) + *input ip must netorder + */ +int +nstack_rd_ip_spec (void *rdkey) +{ + nstack_rd_key *key = (nstack_rd_key *) rdkey; + unsigned int ip_addr = 0; + + ip_addr = ntohl (key->ip_addr); + + if (rd_ismulticast (ip_addr)) + { + if (-1 == g_multi_stackid) + { + g_multi_stackid = nstack_get_stackid_byname (NSTACK_IP_MLSTACKID); + } + return g_multi_stackid; + } + return -1; +} + +int +nstack_rd_ip_default (void *rdkey) +{ + return NSTACK_GET_STACK (0); +} diff --git a/src/nSocket/nstack_rd/nstack_rd_ip.h b/src/nSocket/nstack_rd/nstack_rd_ip.h new file mode 100644 index 0000000..d64956d --- /dev/null +++ b/src/nSocket/nstack_rd/nstack_rd_ip.h @@ -0,0 +1,38 @@ +/* +* +* 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 __NSTACK_RD_IP_H +#define __NSTACK_RD_IP_H + +#define NSTACK_RD_IP_ITEM_COPY(destitem, srcitem){ \ + (destitem)->agetime = (srcitem)->agetime; \ + (destitem)->stack_id = (srcitem)->stack_id; \ + (destitem)->type = (srcitem)->type; \ + (destitem)->ipdata.addr = (srcitem)->ipdata.addr; \ + (destitem)->ipdata.masklen = (srcitem)->ipdata.masklen; \ + (destitem)->ipdata.resev[0] = (srcitem)->ipdata.resev[0]; \ + (destitem)->ipdata.resev[1] = (srcitem)->ipdata.resev[1]; \ +} + +int nstack_rd_ipdata_cpy (void *destdata, void *srcdata); +int nstack_rd_ip_item_insert (nstack_rd_list * hlist, void *rditem); +int nstack_rd_ip_item_find (nstack_rd_list * hlist, void *rdkey, + void *outitem); +int nstack_rd_ip_item_age (nstack_rd_list * hlist); +int nstack_rd_ip_spec (void *rdkey); +int nstack_rd_ip_default (void *rdkey); + +#endif diff --git a/src/nSocket/nstack_rd/nstack_rd_priv.h b/src/nSocket/nstack_rd/nstack_rd_priv.h new file mode 100644 index 0000000..217f1d3 --- /dev/null +++ b/src/nSocket/nstack_rd/nstack_rd_priv.h @@ -0,0 +1,112 @@ +/* +* +* 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 __NSTACK_RD_PRIV_H +#define __NSTACK_RD_PRIV_H +#include "list.h" + +#define NSTACK_RD_SUCCESS (0) +#define NSTACK_RD_FAIL (-1) +#define NSTACK_RD_ITEM_MAX (1024) + +#define NSTACK_RD_AGETIME_MAX (1) +#define NSTACK_SYS_FUN_MAX (16) + +#define RD_STACKX_NAME "stackx" +#define RD_LINUX_NAME "kernel" + +#define RD_STACKX_PLANENAME "nstack-dpdk" +#define RD_LINUX_PLANENAME "nstack-kernel" +#define RD_LINUX_PLANENULL "null" + +#define NSTACK_RD_INDEX_BYIP(ip) (((ip) & 0xff) \ + + (((ip) >> 8)&0xff) \ + + (((ip) >> 16)&0xff) \ + + (((ip) >> 24)&0xff)) + +typedef struct __rd_stack_plane_map +{ + char stackname[STACK_NAME_MAX]; + char planename[RD_PLANE_NAMELEN]; + int stackid; +} rd_stack_plane_map; + +/*route data*/ +typedef struct __rd_data_item +{ + /*route info type , for example base on ip */ + rd_data_type type; + int stack_id; + int agetime; + union + { + rd_ip_data ipdata; + unsigned int proto_type; + }; +} rd_data_item; + +/*stack rd node*/ +typedef struct __nstack_rd_node +{ + struct hlist_node rdnode; + rd_data_item item; +} nstack_rd_node; + +typedef struct __nstack_rd_list +{ + struct hlist_head headlist; +} nstack_rd_list; + +typedef struct __nstack_rd_stack_info +{ + /*stack name */ + rd_stack_plane_map stack; + /*stack id */ + int stack_id; + /*when route info not found, high priority stack was chose, same priority chose fist input one */ + int priority; /*0: highest: route info not found choose first */ +} nstack_rd_stack_info; + +/*rd local data*/ +typedef struct __rd_local_data +{ + nstack_rd_stack_info *pstack_info; + int stack_num; + nstack_rd_list route_list[RD_DATA_TYPE_MAX]; /*route table */ + nstack_get_route_data sys_fun[NSTACK_SYS_FUN_MAX]; /*rd data sys proc function list */ + int fun_num; +} rd_local_data; + +typedef struct __rd_data_proc +{ + int (*rd_item_cpy) (void *destdata, void *srcdata); + int (*rd_item_inset) (nstack_rd_list * hlist, void *rditem); + int (*rd_item_age) (nstack_rd_list * hlist); + int (*rd_item_find) (nstack_rd_list * hlist, void *rdkey, void *outitem); + int (*rd_item_spec) (void *rdkey); + int (*rd_item_defualt) (void *rdkey); +} rd_data_proc; + +extern rd_local_data *g_rd_local_data; +extern rd_data_proc g_rd_cpy[RD_DATA_TYPE_MAX]; + +#define NSTACK_NUM (g_rd_local_data->stack_num) +#define NSTACK_RD_LIST(type) (&(g_rd_local_data->route_list[(type)])) +#define NSTACK_GET_STACK(idx) ((g_rd_local_data->pstack_info)[idx].stack_id) + +int nstack_get_stackid_byname (char *name); + +#endif diff --git a/src/nSocket/nstack_rd/nstack_rd_proto.c b/src/nSocket/nstack_rd/nstack_rd_proto.c new file mode 100644 index 0000000..16f4e1f --- /dev/null +++ b/src/nSocket/nstack_rd/nstack_rd_proto.c @@ -0,0 +1,189 @@ +/* +* +* 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 +#include +#include "nstack_rd_data.h" +#include "nstack_rd.h" +#include "nstack_rd_init.h" +#include "nstack_rd_priv.h" +#include "nstack_rd_proto.h" +#include "nstack_log.h" +#include "nstack_securec.h" + +/*copy rd data*/ +int +nstack_rd_proto_cpy (void *destdata, void *srcdata) +{ + rd_data_item *pitem = (rd_data_item *) destdata; + rd_route_data *pdata = (rd_route_data *) srcdata; + pitem->type = pdata->type; + pitem->proto_type = pdata->proto_type; + return NSTACK_RD_SUCCESS; +} + +/* + * Add an ip segment to the list and sort it in descending order of ip mask length + * If the list already exists in the same list of ip side, then stack_id update + *ip is local byteorder + */ +int +nstack_rd_proto_item_insert (nstack_rd_list * hlist, void *rditem) +{ + nstack_rd_node *pdatanode = NULL; + nstack_rd_node *tempdata = NULL; + struct hlist_node *tempnode = NULL; + rd_data_item *pitem = (rd_data_item *) rditem; + + NSSOC_LOGDBG ("stackid:%d, protocol type:%d was inserted", pitem->stack_id, + pitem->proto_type); + + pdatanode = (nstack_rd_node *) malloc (sizeof (nstack_rd_node)); + if (!pdatanode) + { + NSSOC_LOGERR ("nstack rd item malloc fail"); + return NSTACK_RD_FAIL; + } + int retVal = + MEMSET_S (pdatanode, sizeof (nstack_rd_node), 0, sizeof (nstack_rd_node)); + if (EOK != retVal) + { + NSSOC_LOGERR ("MEMSET_S failed]retVal=%d", retVal); + free (pdatanode); + return NSTACK_RD_FAIL; + } + INIT_HLIST_NODE (&pdatanode->rdnode); + NSTACK_RD_PROTO_ITEM_COPY (&(pdatanode->item), pitem); + if (hlist_empty (&(hlist->headlist))) + { + hlist_add_head (&(pdatanode->rdnode), &(hlist->headlist)); + + return NSTACK_RD_SUCCESS; + + } + + hlist_for_each_entry (tempdata, tempnode, &(hlist->headlist), rdnode) + { + if (tempdata->item.proto_type == pitem->proto_type) + + { + tempdata->item.stack_id = pitem->stack_id; + tempdata->item.agetime = NSTACK_RD_AGETIME_MAX; + free (pdatanode); + return NSTACK_RD_SUCCESS; + } + } + hlist_add_head (&(pdatanode->rdnode), &(hlist->headlist)); + + return NSTACK_RD_SUCCESS; + +} + +/* + *find stackid by ip + *input ip must netorder + */ +int +nstack_rd_proto_item_find (nstack_rd_list * hlist, void *rdkey, void *outitem) +{ + struct hlist_node *tempnode = NULL; + nstack_rd_node *tempdata = NULL; + nstack_rd_key *key = (nstack_rd_key *) rdkey; + rd_data_item *pitem = (rd_data_item *) outitem; + hlist_for_each_entry (tempdata, tempnode, &(hlist->headlist), rdnode) + { + + /*if already exist, just return success */ + if (tempdata->item.proto_type == key->proto_type) + + { + NSTACK_RD_PROTO_ITEM_COPY (pitem, &(tempdata->item)); + return NSTACK_RD_SUCCESS; + } + } + + NSSOC_LOGDBG ("protocol type item not found", key->proto_type); + + return NSTACK_RD_FAIL; +} + +/***************************************************************************** +* Prototype : nstack_rd_ip_item_age +* Description : delete the ip item that have not been add again for one time +* Input : nstack_rd_list *hlist +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nstack_rd_proto_item_age (nstack_rd_list * hlist) +{ + struct hlist_node *tempnode = NULL; + nstack_rd_node *tempdata = NULL; + nstack_rd_node *prevdata = NULL; + struct hlist_node *prevnode = NULL; + NSSOC_LOGINF ("nstack rd ip age begin"); + hlist_for_each_entry (tempdata, tempnode, &(hlist->headlist), rdnode) + { + /*if agetime equal 0, remove it */ + if (tempdata->item.agetime <= 0) + { + if (prevdata) + { + NSSOC_LOGDBG ("stackid:%d, protocol type was aged", + tempdata->item.stack_id, tempdata->item.proto_type); + + hlist_del_init (prevnode); + free (prevdata); + } + prevdata = tempdata; + prevnode = tempnode; + } + else + { + tempdata->item.agetime--; + } + } + if (prevdata) + { + if (tempdata) + { + NSSOC_LOGDBG ("stackid:%d, protocol type was aged", + tempdata->item.stack_id, tempdata->item.proto_type); + } + hlist_del_init (prevnode); + free (prevdata); + } + NSSOC_LOGINF ("nstack rd ip age end"); + return NSTACK_RD_SUCCESS; +} + +/* + *find stackid by spec ip(multicast ip) + *input ip must netorder + */ +int +nstack_rd_proto_spec (void *rdkey) +{ + return -1; +} + +int +nstack_rd_proto_default (void *rdkey) +{ + return -1; +} diff --git a/src/nSocket/nstack_rd/nstack_rd_proto.h b/src/nSocket/nstack_rd/nstack_rd_proto.h new file mode 100644 index 0000000..f3b0311 --- /dev/null +++ b/src/nSocket/nstack_rd/nstack_rd_proto.h @@ -0,0 +1,35 @@ +/* +* +* 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 __NSTACK_RD_PROTO_H +#define __NSTACK_RD_PROTO_H +/* *INDENT-OFF* */ +#define NSTACK_RD_PROTO_ITEM_COPY(destitem, srcitem){ \ + (destitem)->agetime = (srcitem)->agetime; \ + (destitem)->stack_id = (srcitem)->stack_id; \ + (destitem)->type = (srcitem)->type; \ + (destitem)->proto_type = (srcitem)->proto_type; \ +} +/* *INDENT-ON* */ +int nstack_rd_proto_cpy (void *destdata, void *srcdata); +int nstack_rd_proto_item_insert (nstack_rd_list * hlist, void *rditem); +int nstack_rd_proto_item_find (nstack_rd_list * hlist, void *rdkey, + void *outitem); +int nstack_rd_proto_item_age (nstack_rd_list * hlist); +int nstack_rd_proto_spec (void *rdkey); +int nstack_rd_proto_default (void *rdkey); + +#endif /* */ -- cgit 1.2.3-korg