aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQing Chang <qing.chang1@huawei.com>2018-03-13 01:24:25 +0000
committerGerrit Code Review <gerrit@fd.io>2018-03-13 01:24:25 +0000
commiteb88437358ba4021ea4631c1b05a68a05e51d954 (patch)
tree15482c10907c00fa22fc489ea10b850d23c9a4cf /src
parent1b031216ba4cd37943900b8759f50fd0e3a8f1cf (diff)
parentc398e6ec613c1f90ffe33608c511208100e7372f (diff)
Merge "Add the nSocket module for dmm"
Diffstat (limited to 'src')
-rw-r--r--src/nSocket/CMakeLists.txt51
-rw-r--r--src/nSocket/include/declare_syscalls.h51
-rw-r--r--src/nSocket/include/nstack_atomic.h57
-rw-r--r--src/nSocket/include/nstack_dmm_api.h92
-rw-r--r--src/nSocket/include/nstack_eventpoll.h338
-rw-r--r--src/nSocket/include/nstack_ip_addr.h36
-rw-r--r--src/nSocket/include/nstack_rd.h47
-rw-r--r--src/nSocket/include/nstack_rd_init.h45
-rw-r--r--src/nSocket/include/nstack_select.h153
-rw-r--r--src/nSocket/include/nstack_sockops.h55
-rw-r--r--src/nSocket/include/nstack_types.h152
-rw-r--r--src/nSocket/include/select_adapt.h105
-rw-r--r--src/nSocket/kernel/linux_kernel_module.c337
-rw-r--r--src/nSocket/kernel/linux_kernel_module.h61
-rw-r--r--src/nSocket/kernel/linux_kernel_socket.c64
-rw-r--r--src/nSocket/kernel/linux_kernel_socket.h36
-rw-r--r--src/nSocket/nstack/event/epoll/nstack_eventpoll.c1213
-rw-r--r--src/nSocket/nstack/event/select/nstack_select.c756
-rw-r--r--src/nSocket/nstack/event/select/select_adapt.c339
-rw-r--r--src/nSocket/nstack/nstack.c833
-rw-r--r--src/nSocket/nstack/nstack.h121
-rw-r--r--src/nSocket/nstack/nstack_fd_mng.c240
-rw-r--r--src/nSocket/nstack/nstack_fd_mng.h210
-rw-r--r--src/nSocket/nstack/nstack_info_parse.c493
-rw-r--r--src/nSocket/nstack/nstack_info_parse.h56
-rw-r--r--src/nSocket/nstack/nstack_module.c269
-rw-r--r--src/nSocket/nstack/nstack_module.h157
-rw-r--r--src/nSocket/nstack/nstack_nsocket_construct.c43
-rw-r--r--src/nSocket/nstack/nstack_socket.c2816
-rw-r--r--src/nSocket/nstack/nstack_socket.h231
-rw-r--r--src/nSocket/nstack_rd/nstack_rd.c386
-rw-r--r--src/nSocket/nstack_rd/nstack_rd_init.c202
-rw-r--r--src/nSocket/nstack_rd/nstack_rd_ip.c264
-rw-r--r--src/nSocket/nstack_rd/nstack_rd_ip.h38
-rw-r--r--src/nSocket/nstack_rd/nstack_rd_priv.h112
-rw-r--r--src/nSocket/nstack_rd/nstack_rd_proto.c189
-rw-r--r--src/nSocket/nstack_rd/nstack_rd_proto.h35
37 files changed, 10683 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+
+#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 <sys/types.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#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 <semaphore.h>
+#include <sys/epoll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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 <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+#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 <semaphore.h>
+#include <time.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <common_pal_bitwide_adjust.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include<sys/types.h>
+#include<sys/time.h>
+#include<unistd.h>
+#include <string.h>
+#include <pthread.h>
+#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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+
+#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 <pthread.h>
+#include "nstack.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#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 <sys/socket.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#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 <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+#include <math.h>
+#include <string.h>
+
+#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 <semaphore.h>
+#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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#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 <dlfcn.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#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 <dlfcn.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#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 <poll.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#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 <time.h>
+#include <stdarg.h>
+
+#ifndef __USE_GNU
+#define __USE_GNU
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* define RTLD_NEXT */
+#endif
+
+#include <dlfcn.h>
+#include <unistd.h>
+#include <stdio.h>
+#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 <declare_syscalls.h>
+#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 ("addrlen<sizeof(struct sockaddr_in)]addrlen=%u", addrlen);
+ UNLOCK_COMMON (fd, local_lock);
+ return -1;
+ }
+
+ /* for custom socket, choose stack after creating socket. */
+ if (fdInf->ops)
+ {
+ 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 <sys/socket.h>
+#include <poll.h>
+#include <sys/epoll.h>
+
+#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 <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#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 <stdlib.h>
+#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 <stdlib.h>
+#include <arpa/inet.h>
+#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 <stdlib.h>
+#include <arpa/inet.h>
+#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 /* */