summaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack/lwip_src/socket
diff options
context:
space:
mode:
Diffstat (limited to 'stacks/lwip_stack/lwip_src/socket')
-rw-r--r--stacks/lwip_stack/lwip_src/socket/CMakeLists.txt75
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_cfg.h54
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c329
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c143
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h46
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_event.c175
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_event.h46
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_macro.h24
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c766
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h78
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c670
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h159
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c109
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c271
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h67
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_socket.h138
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_tcp.c1682
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_udp.c1149
18 files changed, 5981 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/socket/CMakeLists.txt b/stacks/lwip_stack/lwip_src/socket/CMakeLists.txt
new file mode 100644
index 0000000..8516ef3
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/CMakeLists.txt
@@ -0,0 +1,75 @@
+#########################################################################
+#
+# 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.
+#########################################################################
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fPIE -pie -fPIC -m64 -mssse3 -std=gnu89")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wshadow -Wfloat-equal -Wformat=2")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector -fstack-protector-all")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,relro,-z,now -Wl,--disable-new-dtags")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack -mcmodel=medium")
+
+SET(ADAPT_DIRECTORIES "${PROJECT_SOURCE_DIR}/src/adapt/")
+#SET(DMM_API "${PROJECT_SOURCE_DIR}/src/nSocket/include/")
+
+ADD_DEFINITIONS(-D_GNU_SOURCE -D_FORTIFY_SOURCE=2)
+ADD_DEFINITIONS(-DDPDK_MODULE=0)
+if(WITH_HAL_LIB)
+SET(RTP_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../../src/include/rtp_config.h)
+else()
+ SET(PAL_H_DIRECTORIES "/usr/include/dpdk/")
+ SET(RTP_CONFIG ${PROJECT_SOURCE_DIR}/src/mem/include/common_sys_config.h)
+ INCLUDE_DIRECTORIES(
+ ${PAL_H_DIRECTORIES}
+ ${ADAPT_DIRECTORIES}
+# ${DMM_API}
+ )
+endif()
+SET(COMPLE_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/compile_config.h)
+#SET(MGR_COM ${PROJECT_SOURCE_DIR}/src/framework/ipc/mgr_com/mgr_com.h)
+SET(MGR_COM ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/ipc/mgr_com/mgr_com.h)
+ADD_DEFINITIONS(-include ${RTP_CONFIG})
+ADD_DEFINITIONS(-include ${COMPLE_CONFIG})
+ADD_DEFINITIONS(-include ${MGR_COM})
+if(WITH_SECUREC_LIB)
+LINK_LIBRARIES(pthread rt securec)
+else()
+LINK_LIBRARIES(pthread rt)
+endif()
+LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC})
+INCLUDE_DIRECTORIES(
+ ${CMAKE_CURRENT_LIST_DIR}/../../../../thirdparty/json/json-c-0.12.1/
+ ${CMAKE_CURRENT_LIST_DIR}/../../../../thirdparty/glog/glog-0.3.5/src/
+ ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/
+ ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/
+ ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/
+# ${ADAPT_DIRECTORIES}
+# ${DMM_API}
+)
+
+FILE(GLOB COMMON ../common/*.c)
+FILE(GLOB SOCKET ./*.c)
+ADD_LIBRARY(socket STATIC ${COMMON} ${SOCKET})
+ADD_DEPENDENCIES(socket JSON GLOG DPDK)
+TARGET_INCLUDE_DIRECTORIES(
+ socket
+ PRIVATE
+ ../common/
+ ./
+ ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/
+ ${CMAKE_CURRENT_LIST_DIR}/../../src/include/
+ ${CMAKE_CURRENT_LIST_DIR}/../../src/mem/include/
+ ${CMAKE_CURRENT_LIST_DIR}/../../src/mem/nsfw_shmem/
+ ${CMAKE_CURRENT_LIST_DIR}/../../src/sbr/
+)
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_cfg.h b/stacks/lwip_stack/lwip_src/socket/stackx_cfg.h
new file mode 100644
index 0000000..e6d100d
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_cfg.h
@@ -0,0 +1,54 @@
+/*
+*
+* 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 STACKX_CONTAINER_CFG_H
+#define STACKX_CONTAINER_CFG_H
+#include "types.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define SBR_MAX_CFG_PATH_LEN 256
+#define SBR_MAX_CONTAINER_IP_NUM 1024
+#define SBR_MAX_CFG_FILE_SIZE (1 * 1024 * 1024)
+
+typedef struct
+{
+ u32 ip;
+ u32 mask_len;
+} sbr_container_ip;
+
+typedef struct
+{
+ sbr_container_ip ip_array[SBR_MAX_CONTAINER_IP_NUM];
+ u32 ip_num;
+} sbr_container_ip_group;
+
+extern sbr_container_ip_group g_container_ip_group;
+
+int sbr_init_cfg();
+int sbr_get_src_ip(u32 dst_ip, u32 * src_ip);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c b/stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c
new file mode 100644
index 0000000..8c6ab46
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c
@@ -0,0 +1,329 @@
+/*
+*
+* 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include "stackx_cfg.h"
+#include "json.h"
+#include "nstack_log.h"
+#include "spl_def.h"
+#include "nstack_securec.h"
+#include "stackx_ip_addr.h"
+
+sbr_container_ip_group g_container_ip_group;
+
+/*****************************************************************************
+* Prototype : sbr_parse_container_ip_json
+* Description : parse port json
+* Input : char* param
+* Output : None
+* Return Value : static void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static void sbr_parse_container_ip_json(char *param)
+{
+ int retval;
+ struct json_object *obj = json_tokener_parse(param);
+ struct json_object *container_id_obj = NULL;
+ struct json_object *ports_list_obj = NULL;
+ struct json_object *ip_cidr_list_obj = NULL;
+
+ if (!obj)
+ {
+ NSSBR_LOGERR("json_tokener_parse failed");
+ return;
+ }
+
+ json_object_object_get_ex(obj, "containerID", &container_id_obj);
+ if (!container_id_obj)
+ {
+ NSSBR_LOGERR("can't get containerID");
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex(obj, "ports_list", &ports_list_obj);
+ if (ports_list_obj)
+ {
+ int i;
+ int port_num = json_object_array_length(ports_list_obj);
+
+ if (0 == port_num)
+ {
+ NSSBR_LOGERR("port num is 0");
+ goto RETURN_ERROR;
+ }
+
+ for (i = 0; i < port_num; i++)
+ {
+ struct json_object *port_obj =
+ json_object_array_get_idx(ports_list_obj, i);
+ json_object_object_get_ex(port_obj, "ip_cidr", &ip_cidr_list_obj);
+ if (ip_cidr_list_obj)
+ {
+ int j;
+ int ip_cidr_num = json_object_array_length(ip_cidr_list_obj);
+ for (j = 0; j < ip_cidr_num; ++j)
+ {
+ struct json_object *ip_cidr_obj =
+ json_object_array_get_idx(ip_cidr_list_obj, j);
+ if (ip_cidr_obj)
+ {
+ char tmp[32] = { 0 };
+ const char *ip_cidr =
+ json_object_get_string(ip_cidr_obj);
+ if ((NULL == ip_cidr) || (ip_cidr[0] == 0))
+ {
+ NSSBR_LOGERR("ip is empty");
+ goto RETURN_ERROR;
+ }
+
+ const char *sub = strstr(ip_cidr, "/");
+ if ((NULL == sub)
+ || (sizeof(tmp) - 1 <
+ (unsigned int) (sub - ip_cidr))
+ || (strlen(sub) > sizeof(tmp) - 1))
+ {
+ NSSBR_LOGERR("ip format is not ok");
+ goto RETURN_ERROR;
+ }
+
+ retval =
+ strncpy_s(tmp, sizeof(tmp), ip_cidr,
+ (size_t) (sub - ip_cidr));
+ if (EOK != retval)
+ {
+ NSSBR_LOGERR("STRNCPY_S failed]ret=%d", retval);
+ goto RETURN_ERROR;
+ }
+
+ struct in_addr addr;
+ retval =
+ memset_s(&addr, sizeof(addr), 0, sizeof(addr));
+ if (EOK != retval)
+ {
+ NSSBR_LOGERR("MEMSET_S failed]ret=%d", retval);
+ goto RETURN_ERROR;
+ }
+
+ retval = spl_inet_aton(tmp, &addr);
+ if (0 == retval)
+ {
+ NSSBR_LOGERR("spl_inet_aton failed]ret=%d",
+ retval);
+ goto RETURN_ERROR;
+ }
+
+ g_container_ip_group.
+ ip_array[g_container_ip_group.ip_num].ip =
+ addr.s_addr;
+ int mask_len = atoi(sub + 1);
+ if ((mask_len <= 0) || (mask_len > 32))
+ {
+ NSSBR_LOGERR("mask len is not ok");
+ goto RETURN_ERROR;
+ }
+
+ g_container_ip_group.
+ ip_array[g_container_ip_group.ip_num].mask_len =
+ (u32) mask_len;
+ g_container_ip_group.ip_num++;
+
+ if (g_container_ip_group.ip_num >=
+ SBR_MAX_CONTAINER_IP_NUM)
+ {
+ NSSBR_LOGWAR("container ip num is full]ip_num=%u",
+ g_container_ip_group.ip_num);
+ goto RETURN_OK;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ NSSBR_LOGERR("can't get ports_list");
+ goto RETURN_ERROR;
+ }
+
+ RETURN_OK:
+ json_object_put(obj);
+ NSSBR_LOGINF("container ip num is %u", g_container_ip_group.ip_num);
+ u32 idx;
+ for (idx = 0; idx < g_container_ip_group.ip_num; ++idx)
+ {
+ NSSBR_LOGDBG("container ip=0x%08x",
+ g_container_ip_group.ip_array[idx].ip);
+ }
+ return;
+
+ RETURN_ERROR:
+ json_object_put(obj);
+ if (memset_s
+ (&g_container_ip_group, sizeof(sbr_container_ip_group), 0,
+ sizeof(sbr_container_ip_group)) != EOK)
+ {
+ NSSBR_LOGERR("MEMSET_S failed");
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_cfg_path
+* Description : get cfg path
+* Input : None
+* Output : None
+* Return Value : NSTACK_STATIC const char*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC const char *sbr_get_cfg_path()
+{
+ static char cfg_file[SBR_MAX_CFG_PATH_LEN] =
+ "/canal/output/portinfo.json";
+ return cfg_file;
+}
+
+/*****************************************************************************
+* Prototype : sbr_init_cfg
+* Description : init cfg from file
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_init_cfg()
+{
+ int ret;
+ off_t file_len = 0;
+ off_t buff_len = 0;
+ char *buff = NULL;
+ const char *cfg_file = sbr_get_cfg_path(); /* no need check ret */
+
+ int fp = open(cfg_file, O_RDONLY);
+
+ if (fp < 0)
+ {
+ NSSBR_LOGWAR("failed to open file]file name=%s", cfg_file);
+ goto RETURN_ERROR;
+ }
+
+ file_len = lseek(fp, 0, SEEK_END);
+ if (file_len <= 0)
+ {
+ NSSBR_LOGWAR("failed to get file len]file name=%s", cfg_file);
+ goto RETURN_ERROR;
+ }
+
+ if (file_len > SBR_MAX_CFG_FILE_SIZE)
+ {
+ NSSBR_LOGWAR
+ ("file len is too big]file len=%d, max len=%d, file name=%s",
+ file_len, SBR_MAX_CFG_FILE_SIZE, cfg_file);
+ goto RETURN_ERROR;
+ }
+
+ ret = lseek(fp, 0, SEEK_SET);
+ if (ret < 0)
+ {
+ NSSBR_LOGWAR("seek to start failed]file name=%s", cfg_file);
+ goto RETURN_ERROR;
+ }
+
+ buff_len = file_len + 1;
+ buff = (char *) malloc(buff_len);
+ if (!buff)
+ {
+ NSSBR_LOGWAR("malloc buff failed]buff_len=%d", buff_len);
+ goto RETURN_ERROR;
+ }
+
+ ret = memset_s(buff, buff_len, 0, buff_len);
+ if (EOK != ret)
+ {
+ NSSBR_LOGWAR("MEMSET_S failed]ret=%d.", ret);
+ goto RETURN_ERROR;
+ }
+
+ ret = read(fp, buff, buff_len - 1);
+ if (ret <= 0)
+ {
+ NSSBR_LOGWAR("read failed]ret=%d", ret);
+ goto RETURN_ERROR;
+ }
+
+ sbr_parse_container_ip_json(buff);
+ close(fp);
+ free(buff);
+ return 0;
+
+ RETURN_ERROR:
+ if (fp >= 0)
+ {
+ close(fp);
+ }
+
+ if (buff)
+ {
+ free(buff);
+ }
+
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_src_ip
+* Description : get src ip from cfg
+* Input : u32 dst_ip
+* u32* src_ip
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_get_src_ip(u32 dst_ip, u32 * src_ip)
+{
+ if (!src_ip)
+ {
+ NSSBR_LOGERR("src_ip is NULL");
+ return -1;
+ }
+
+ u32 i;
+ for (i = 0; i < g_container_ip_group.ip_num; ++i)
+ {
+ unsigned int mask = ~0;
+ mask = (mask << (32 - g_container_ip_group.ip_array[i].mask_len));
+ mask = htonl(mask);
+ if ((dst_ip & mask) == (g_container_ip_group.ip_array[i].ip & mask))
+ {
+ *src_ip = g_container_ip_group.ip_array[i].ip;
+ NSSBR_LOGDBG("find src ip]container_ip=0x%08x,dest_ip=0x%08x",
+ *src_ip, dst_ip);
+ return 0;
+ }
+ }
+
+ NSSBR_LOGDBG("can't find src ip]dest_ip=0x%08x", dst_ip);
+ return -1;
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c
new file mode 100644
index 0000000..da62381
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c
@@ -0,0 +1,143 @@
+/*
+*
+* 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 "stackx_epoll_api.h"
+#include "stackx_spl_share.h"
+#include "common_pal_bitwide_adjust.h"
+#include "nstack_dmm_adpt.h"
+#include "nstack_epoll_api.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif /* _cplusplus */
+
+void epoll_triggle_event_from_api(sbr_socket_t * sock, int op)
+{
+ struct spl_netconn *conn = sbr_get_conn(sock);
+ void *epInfo = ADDR_SHTOL(conn->epInfo);
+ //NSPOL_LOGDBG(SOCKETS_DEBUG, "enter]fd=%d,op=%d", sock, op);
+ switch (op)
+ {
+ case EPOLL_API_OP_RECV:
+ break;
+ case EPOLL_API_OP_SEND:
+ if (conn->epoll_flag && epInfo)
+ {
+ NSTACK_EPOLL_EVENT_ADD(epInfo, EPOLLOUT, EVENT_INFORM_APP);
+ }
+ break;
+ case EPOLL_API_OP_STACK_RECV:
+ if (conn->epoll_flag && epInfo)
+ {
+ NSTACK_EPOLL_EVENT_ADD(epInfo, EPOLLIN, EVENT_INFORM_APP);
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+/*
+ * This function will be registed to application
+ * The context will be in the application
+ */
+void *stackx_eventpoll_triggle(sbr_socket_t * sock, int triggle_ops,
+ void *pdata, void *event)
+{
+ struct spl_netconn *conn = sbr_get_conn(sock);
+ unsigned int events = 0;
+ if (!conn)
+ {
+ NSPOL_LOGINF(SOCKETS_DEBUG, "get socket failed]fd=%d", sock->fd);
+ return NULL;
+ }
+
+ NSPOL_LOGINF(SOCKETS_DEBUG,
+ "]fd=%d,triggle_ops=%d conn=%p pdata=%p", sock->fd,
+ triggle_ops, conn, pdata);
+ /*
+ * sock->epoll_flag must be set before sock->rcvevent check.
+ * Consider this Scenario : 1) network stack has got one packet, but event_callback not called yet
+ * 2) Do epoll ctl add, then stackx triggle will check event, it will get 0
+ * 3) network stack call event_callback , it will check epoll_flag
+ * So, if epoll_flag not set before sock->rcvent check, neither of network stack and stackx triggle
+ * will add this event to epoll. because : for network stack, event_callback check epoll_flag fail
+ * for stackx triggle, event check fail.
+ */
+ if (nstack_ep_triggle_add == triggle_ops)
+ {
+ /*log info */
+ conn->epInfo = pdata;
+ __sync_fetch_and_add(&conn->epoll_flag, 1);
+ }
+
+ if ((!((conn->rcvevent == 0) && (sbr_get_fd_share(sock)->lastdata == 0)
+ && (sbr_get_fd_share(sock)->lastoffset == 0))))
+ events |= EPOLLIN;
+ if (conn->sendevent)
+ events |= EPOLLOUT;
+ if (conn->errevent)
+ events |= conn->errevent;
+
+ switch (triggle_ops)
+ {
+ case nstack_ep_triggle_add:
+ case nstack_ep_triggle_mod:
+ *(int *) event = events;
+ break;
+ case nstack_ep_triggle_del:
+ if (conn->epoll_flag > 0)
+ {
+ __sync_fetch_and_sub(&conn->epoll_flag, 1);
+ }
+ events = 0;
+ break;
+ default:
+ return NULL;
+ }
+ return conn;
+}
+
+/*
+ * This function will be registed to application
+ * The context will be in the application
+ * RETURN VALUE : Event exists in current protocol
+ */
+int stackx_eventpoll_getEvt(sbr_socket_t * sock)
+{
+ struct spl_netconn *conn = sbr_get_conn(sock);
+ int tevent = 0;
+ if (!((conn->rcvevent == 0) && (sbr_get_fd_share(sock)->lastdata == 0)
+ && (sbr_get_fd_share(sock)->lastoffset == 0)))
+ {
+ tevent |= EPOLLIN;
+ }
+
+ if (conn->sendevent)
+ {
+ tevent |= EPOLLOUT;
+ }
+ return tevent;
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif /* _cplusplus */
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h
new file mode 100644
index 0000000..9bbd695
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h
@@ -0,0 +1,46 @@
+/*
+*
+* 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 STACKX_EPOLL_API_H
+#define STACKX_EPOLL_API_H
+#include "stackx_socket.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef enum
+{
+ EPOLL_API_OP_RECV,
+ EPOLL_API_OP_SEND,
+ EPOLL_API_OP_STACK_RECV
+} EPOLL_TRIGGLE_EVENT_API_OPS_T;
+
+extern void epoll_triggle_event_from_api(sbr_socket_t * sock, int op);
+extern int stackx_eventpoll_getEvt(sbr_socket_t * sock);
+extern void *stackx_eventpoll_triggle(sbr_socket_t * sock,
+ int triggle_ops,
+ void *pdata, void *event);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_event.c b/stacks/lwip_stack/lwip_src/socket/stackx_event.c
new file mode 100644
index 0000000..3b3eb00
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_event.c
@@ -0,0 +1,175 @@
+/*
+*
+* 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 "stackx_spl_share.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_event.h"
+
+#define FREE_FD_SET(readfd, writefd, exceptfd) {\
+if(readfd)\
+free(readfd);\
+if(writefd)\
+free(writefd);\
+if(exceptfd)\
+free(exceptfd);\
+}
+
+#define FREE_SELECT_BITS(read_set, write_set, err_set)\
+{\
+ if((read_set)->fds_bits)\
+ free((read_set)->fds_bits);\
+ if((write_set)->fds_bits)\
+ free((write_set)->fds_bits);\
+ if((err_set)->fds_bits)\
+ free((err_set)->fds_bits);\
+}
+
+NSTACK_STATIC inline int sbr_fd_copy(nstack_fd_set * psrc,
+ nstack_fd_set * pdst, u32 size)
+{
+ return memcpy_s(pdst->fds_bits, size, psrc->fds_bits, size);
+}
+
+int
+lwip_try_select(int fdsize, fd_set * fdread, fd_set * fdwrite,
+ fd_set * fderr, struct timeval *timeout)
+{
+ int i;
+ int nready = 0;
+ nstack_fd_set *read_out;
+ nstack_fd_set *write_out;
+ nstack_fd_set *err_out;
+ nstack_fd_set *readfd = (nstack_fd_set *) fdread;
+ nstack_fd_set *writefd = (nstack_fd_set *) fdwrite;
+ nstack_fd_set *exceptfd = (nstack_fd_set *) fderr;
+ sbr_socket_t *sock;
+ spl_netconn_t *conn;
+
+ if ((fdsize >= NSTACK_SETSIZE) || (fdsize < 0))
+ {
+ return 0;
+ }
+ read_out = malloc(sizeof(nstack_fd_set));
+ write_out = malloc(sizeof(nstack_fd_set));
+ err_out = malloc(sizeof(nstack_fd_set));
+ if ((!read_out) || (!write_out) || (!err_out))
+ {
+ NSPOL_LOGERR("malloc nstack_fd_set fail");
+ FREE_FD_SET(read_out, write_out, err_out);
+ return -1;
+ }
+
+ u32 fd_set_size = sizeof(unsigned char) * ((SBR_MAX_FD_NUM + 7) / 8);
+ read_out->fds_bits = (unsigned char *) malloc(fd_set_size);
+ write_out->fds_bits = (unsigned char *) malloc(fd_set_size);
+ err_out->fds_bits = (unsigned char *) malloc(fd_set_size);
+ if ((!read_out->fds_bits) || (!write_out->fds_bits)
+ || (!err_out->fds_bits))
+ {
+ NSPOL_LOGERR("malloc nstack_fd_set fd_bits fail");
+ nready = -1;
+ goto return_over;
+ }
+
+ int ret = NSTACK_FD_ZERO(read_out, fd_set_size);
+ int ret1 = NSTACK_FD_ZERO(write_out, fd_set_size);
+ int ret2 = NSTACK_FD_ZERO(err_out, fd_set_size);
+
+ if ((EOK != ret) || (EOK != ret1) || (EOK != ret2))
+ {
+ NSPOL_LOGERR("NSTACK_FD_ZERO fail");
+ nready = -1;
+ goto return_over;
+ }
+
+ for (i = 0; i < fdsize; i++)
+ {
+ if (!((readfd && NSTACK_FD_ISSET(i, readfd))
+ || (writefd && NSTACK_FD_ISSET(i, writefd))
+ || (exceptfd && NSTACK_FD_ISSET(i, exceptfd))))
+ {
+ continue;
+ }
+ sock = sbr_lookup_sk(i);
+ if (sock == NULL)
+ {
+ errno = EBADF;
+ nready = -1;
+ goto return_over;
+ }
+ conn = sbr_get_conn(sock);
+ if (!conn)
+ {
+ errno = EBADF;
+ nready = -1;
+ goto return_over;
+ }
+ if (readfd && NSTACK_FD_ISSET(i, readfd) &&
+ ((sbr_get_fd_share(sock)->lastdata != NULL)
+ || (conn->rcvevent > 0)))
+ {
+ NSTACK_FD_SET(i, read_out);
+ nready++;
+ }
+ if (writefd && NSTACK_FD_ISSET(i, writefd) && (conn->sendevent != 0))
+ {
+ NSTACK_FD_SET(i, write_out);
+ nready++;
+ }
+ if (exceptfd && NSTACK_FD_ISSET(i, exceptfd) && (conn->errevent != 0))
+ {
+ NSTACK_FD_SET(i, write_out);
+ nready++;
+ }
+ }
+
+ //TODO: need to handle fd_set and nstack_fd_set memory issue
+ if (readfd)
+ {
+ if (EOK != sbr_fd_copy(read_out, readfd, fd_set_size))
+ {
+ NSPOL_LOGERR("NSTACK_FD_COPY fail");
+ nready = -1;
+ goto return_over;
+ }
+ }
+
+ if (writefd)
+ {
+ if (EOK != sbr_fd_copy(write_out, writefd, fd_set_size))
+ {
+ NSPOL_LOGERR("NSTACK_FD_COPY fail");
+ nready = -1;
+ goto return_over;
+ }
+ }
+
+ if (exceptfd)
+ {
+ if (EOK != sbr_fd_copy(err_out, exceptfd, fd_set_size))
+ {
+ NSPOL_LOGERR("NSTACK_FD_COPY fail");
+ nready = -1;
+ goto return_over;
+ }
+ }
+
+ return_over:
+
+ FREE_SELECT_BITS(read_out, write_out, err_out);
+ FREE_FD_SET(read_out, write_out, err_out);
+ return nready;
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_event.h b/stacks/lwip_stack/lwip_src/socket/stackx_event.h
new file mode 100644
index 0000000..6335fc2
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_event.h
@@ -0,0 +1,46 @@
+/*
+*
+* 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 __STACKX_EVENT_H__
+#define __STACKX_EVENT_H__
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "stackx_socket.h"
+#include "nstack_securec.h"
+#include "sbr_res_mgr.h"
+#include "sbr_index_ring.h"
+#define NSTACK_SETSIZE SBR_MAX_FD_NUM
+
+typedef struct
+{
+ unsigned char *fds_bits; //(NSTACK_SETSIZE + 7) / 8
+} __attribute__ ((packed)) nstack_fd_set;
+
+#define NSTACK_FD_SET(n, p) ((p)->fds_bits[(n)/8]|=1U<<((n)&0x07))
+#define NSTACK_FD_ISSET(n,p) (((p)->fds_bits[(n)/8]&(1U<<((n)&0x07)))?1:0)
+#define NSTACK_FD_CLR(n,p) ((p)->fds_bits[(n)/8]&=~(1U<<((n)&0x07)))
+#define NSTACK_FD_ZERO(p, mem_size) (memset_s((void *)(p->fds_bits), mem_size,0,mem_size))
+#define NSTACK_FD_OR(p1 ,p2) {\
+ int i;\
+ for(i = 0; i < (NSTACK_SETSIZE+7)/8; i++){\
+ (p1)->fds_bits[i] |= (p2)->fds_bits[i];\
+ }\
+}
+
+#endif /* __STACKX_EVENT_H__ */
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_macro.h b/stacks/lwip_stack/lwip_src/socket/stackx_macro.h
new file mode 100644
index 0000000..96a0b91
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_macro.h
@@ -0,0 +1,24 @@
+/*
+*
+* 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 STACKX_MACRO_H
+#define STACKX_MACRO_H
+
+#ifndef SBR_USE_LOCK
+#define SBR_USE_LOCK
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c
new file mode 100644
index 0000000..38cf620
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c
@@ -0,0 +1,766 @@
+/*
+*
+* 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 "stackx_msg_handler.h"
+#include "stackx_spl_share.h"
+#include "stackx_spl_msg.h"
+#include "nsfw_msg_api.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_res_mgr.h"
+#include "stackx_prot_com.h"
+#include "nstack_securec.h"
+//#include "stackx_dfx_api.h"
+
+#define SBR_MSG_MALLOC(sk) msg_malloc(ss_get_msg_pool(sbr_get_conn(sk)))
+#define SBR_MSG_FREE(msg) msg_free(msg)
+
+#define SBR_MSG_POST(msg, ring) \
+ do { \
+ if (MSG_ASYN_POST == msg->param.op_type)\
+ {\
+ if (msg_post(msg, ring) < 0)\
+ {\
+ SBR_MSG_FREE(msg); \
+ NSSBR_LOGERR("msg_post failed]major=%u,minor=%u,type=%u", \
+ msg->param.major_type, msg->param.minor_type, msg->param.op_type); \
+ }\
+ } \
+ else \
+ {\
+ if (msg_post(msg, ring) < 0)\
+ {\
+ msg->param.err = ECONNABORTED; \
+ NSSBR_LOGERR("msg_post_with_ref failed]major=%u,minor=%u,type=%u", \
+ msg->param.major_type, msg->param.minor_type, msg->param.op_type); \
+ }\
+ } \
+ } while (0)
+
+#define SBR_MSG_POST_RET(msg, ring, ret) \
+ do { \
+ if (MSG_ASYN_POST == msg->param.op_type)\
+ {\
+ if ((ret = msg_post(msg, ring)) < 0)\
+ {\
+ SBR_MSG_FREE(msg); \
+ NSSBR_LOGERR("msg_post failed]major=%u,minor=%u,type=%u", \
+ msg->param.major_type, msg->param.minor_type, msg->param.op_type); \
+ }\
+ } \
+ else \
+ {\
+ if ((ret = msg_post(msg, ring)) < 0)\
+ {\
+ msg->param.err = ECONNABORTED; \
+ NSSBR_LOGERR("msg_post_with_ref failed]major=%u,minor=%u,type=%u", \
+ msg->param.major_type, msg->param.minor_type, msg->param.op_type); \
+ }\
+ } \
+ } while (0)
+
+NSTACK_STATIC inline void
+_sbr_construct_msg(data_com_msg * m, u16 major_type, u16 minor_type,
+ u16 type, sbr_socket_t * sk)
+{
+ m->param.module_type = MSG_MODULE_SBR;
+ m->param.major_type = major_type;
+ m->param.minor_type = minor_type;
+ m->param.err = 0;
+ m->param.op_type = type;
+ sys_sem_init(&m->param.op_completed);
+ m->param.receiver = ss_get_recv_obj(sbr_get_conn(sk));
+ m->param.comm_receiver = ss_get_comm_private_data(sbr_get_conn(sk));
+ m->param.extend_member_bit = 0;
+}
+
+#define sbr_construct_msg(m, major_type, minor_type, type, sk) { \
+ _sbr_construct_msg(m, major_type, minor_type, type, sk); \
+ NSSBR_LOGINF("fd=%d,conn=%p,private_data=%p", sk->fd, sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); \
+ }
+
+#define sbr_construct_msg_dbg(m, major_type, minor_type, type, sk) { \
+ _sbr_construct_msg(m, major_type, minor_type, type, sk); \
+ NSSBR_LOGDBG("fd=%d,conn=%p,private_data=%p", sk->fd, sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); \
+ }
+
+/*****************************************************************************
+* Prototype : sbr_attach_msg
+* Description : use buf's msg first
+* Input : sbr_socket_t * sk
+* struct pbuf* buf
+* Output : None
+* Return Value : static inline data_com_msg*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline data_com_msg *sbr_attach_msg(sbr_socket_t * sk,
+ struct spl_pbuf *buf)
+{
+ data_com_msg *m = NULL;
+ if (!sk)
+ {
+ return m;
+ }
+
+ if (buf && buf->msg)
+ {
+ m = (data_com_msg *) ADDR_SHTOL(buf->msg);
+ }
+ else
+ {
+ m = SBR_MSG_MALLOC(sk);
+ }
+
+ return m;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_socket
+* Description : create socket
+* Input : sbr_socket_t * sk
+* netconn_type_t type
+* u8 proto
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_handle_socket(sbr_socket_t * sk, spl_netconn_type_t type, u8 proto)
+{
+ data_com_msg *m = SBR_MSG_MALLOC(sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_NEWCONN,
+ MSG_SYN_POST, sk);
+ msg_new_netconn *p = (msg_new_netconn *) m->buffer;
+ p->conn = (spl_netconn_t *) ADDR_LTOSH(sbr_get_conn(sk));
+ p->type = type;
+ p->proto = proto;
+ p->socket = sk->fd;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+ int err = sbr_spl_err_to_errno(m->param.err);
+ SBR_MSG_FREE(m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR("handle socket failed]fd=%d,type=%d,proto=%u,err=%d",
+ sk->fd, type, proto, err);
+ sbr_set_sk_errno(sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_bind
+* Description : bind
+* Input : sbr_socket_t * sk
+* spl_ip_addr_t * addr
+* u16 port
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_handle_bind(sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port)
+{
+ data_com_msg *m = SBR_MSG_MALLOC(sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_BIND, MSG_SYN_POST,
+ sk);
+ msg_bind *p = (msg_bind *) m->buffer;
+ p->ipaddr = *addr;
+ p->port = port;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+ int err = sbr_spl_err_to_errno(m->param.err);
+ SBR_MSG_FREE(m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR("handle bind failed]fd=%d,err=%d", sk->fd, err);
+ sbr_set_sk_errno(sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+int sbr_handle_listen(sbr_socket_t * sk, int backlog)
+{
+ data_com_msg *m = SBR_MSG_MALLOC(sk);
+
+ if (!m)
+ {
+ sbr_set_sk_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_LISTEN,
+ MSG_SYN_POST, sk);
+ msg_listen *p = (msg_listen *) m->buffer;
+ p->conn_pool = sbr_get_conn_pool();
+ p->backlog = backlog;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+ int err = sbr_spl_err_to_errno(m->param.err);
+ SBR_MSG_FREE(m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR("handle listen failed]fd=%d,err=%d", sk->fd, err);
+ sbr_set_sk_errno(sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_connect
+* Description : connect
+* Input : sbr_socket_t * sk
+* spl_ip_addr_t * addr
+* u16 port
+* spl_ip_addr_t* local_ip
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_connect(sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port,
+ spl_ip_addr_t * local_ip)
+{
+ data_com_msg *m = SBR_MSG_MALLOC(sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_CONNECT,
+ MSG_SYN_POST, sk);
+ msg_connect *p = (msg_connect *) m->buffer;
+ p->local_ip = *local_ip;
+ p->ipaddr = *addr;
+ p->port = port;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+ int err = sbr_spl_err_to_errno(m->param.err);
+ SBR_MSG_FREE(m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR("handle connect failed]fd=%d,err=%d", sk->fd, err);
+ sbr_set_sk_errno(sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_get_name
+* Description : get name
+* Input : sbr_socket_t * sk
+* struct sockaddr * name
+* socklen_t * namelen
+* u8 cmd
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_get_name(sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen, u8 cmd)
+{
+ data_com_msg *m = SBR_MSG_MALLOC(sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_GETSOCK_NAME,
+ MSG_SYN_POST, sk);
+ msg_getaddrname *p = (msg_getaddrname *) m->buffer;
+ p->cmd = cmd;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+ int err = sbr_spl_err_to_errno(m->param.err);
+ if (err != 0)
+ {
+ NSSBR_LOGERR("handle get name failed]fd=%d,err=%d", sk->fd, err);
+ goto error;
+ }
+ else
+ {
+ if (*namelen > sizeof(p->sock_addr))
+ {
+ *namelen = sizeof(p->sock_addr);
+ }
+
+ int ret = memcpy_s(name, *namelen, &p->sock_addr, *namelen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ err = EINVAL;
+ goto error;
+ }
+
+ *namelen = sizeof(p->sock_addr);
+ }
+
+ SBR_MSG_FREE(m);
+ return 0;
+
+ error:
+ sbr_set_sk_errno(sk, err);
+ SBR_MSG_FREE(m);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_setsockopt
+* Description : msg box will changed in IP_TOS
+* Input : sbr_socket_t * sk
+* int level
+* int optname
+* const void *optval
+* socklen_t optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_setsockopt(sbr_socket_t * sk, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ data_com_msg *m = SBR_MSG_MALLOC(sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_SET_SOCK_OPT,
+ MSG_SYN_POST, sk);
+ msg_setgetsockopt *p = (msg_setgetsockopt *) m->buffer;
+ p->extend_member_bit = 0;
+ p->level = level;
+ p->optname = optname;
+ p->msg_box = NULL; /* init the value to avoid unexpected consequences */
+
+ if (optlen > sizeof(p->optval))
+ {
+ optlen = sizeof(p->optval);
+ }
+
+ p->optlen = optlen;
+ int err;
+ int ret = memcpy_s(&p->optval, sizeof(p->optval), optval, optlen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ err = EINVAL;
+ goto error;
+ }
+
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+ err = sbr_spl_err_to_errno(m->param.err);
+ if (err != 0)
+ {
+ NSSBR_LOGERR("handle setsockopt failed]fd=%d,err=%d", sk->fd, err);
+ goto error;
+ }
+
+ if (IPPROTO_IP == level && IP_TOS == optname && p->msg_box)
+ {
+ ss_set_msg_box(sbr_get_conn(sk),
+ (mring_handle) ADDR_SHTOL(p->msg_box));
+ }
+
+ SBR_MSG_FREE(m);
+ return 0;
+
+ error:
+ sbr_set_sk_errno(sk, err);
+ SBR_MSG_FREE(m);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_getsockopt
+* Description : get sockopt
+* Input : sbr_socket_t * sk
+* int level
+* int optname
+* void *optval
+* socklen_t* optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_getsockopt(sbr_socket_t * sk, int level, int optname,
+ void *optval, socklen_t * optlen)
+{
+ data_com_msg *m = SBR_MSG_MALLOC(sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_GET_SOCK_OPT,
+ MSG_SYN_POST, sk);
+ msg_setgetsockopt *p = (msg_setgetsockopt *) m->buffer;
+ p->extend_member_bit = 0;
+ p->level = level;
+ p->optname = optname;
+
+ if (*optlen > sizeof(p->optval))
+ {
+ *optlen = sizeof(p->optval);
+ }
+
+ p->optlen = *optlen;
+ int err;
+ int ret = memcpy_s(&p->optval, sizeof(p->optval), optval, *optlen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ err = EINVAL;
+ goto error;
+ }
+
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+
+ err = sbr_spl_err_to_errno(m->param.err);
+ if (err != 0)
+ {
+ NSSBR_LOGERR("handle getsockopt failed]fd=%d,err=%d", sk->fd, err);
+ goto error;
+ }
+
+ ret = memcpy_s(optval, *optlen, &p->optval.int_optval, *optlen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ err = EINVAL;
+ goto error;
+ }
+
+ SBR_MSG_FREE(m);
+ return 0;
+
+ error:
+ sbr_set_sk_errno(sk, err);
+ SBR_MSG_FREE(m);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_close
+* Description : need care msg_box_ref,make sure to finalize this message
+* Input : sbr_socket_t * sk
+* u8 how
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_handle_close(sbr_socket_t * sk, u8 how)
+{
+ data_com_msg *m = sbr_attach_msg(sk,
+ (struct spl_pbuf *)
+ ADDR_SHTOL(sbr_get_fd_share
+ (sk)->recoder.head));
+
+ if (!m)
+ {
+ NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_DELCON,
+ MSG_ASYN_POST, sk);
+ msg_delete_netconn *p = (msg_delete_netconn *) m->buffer;
+ p->extend_member_bit = 0;
+ p->buf = NULL;
+ p->time_started = sys_now();
+ p->shut = how;
+ p->pid = get_sys_pid();
+ p->conn = (spl_netconn_t *) ADDR_LTOSH(sbr_get_conn(sk));
+ p->notify_omc = FALSE;
+ p->msg_box_ref = SPL_MSG_BOX_NUM;
+
+ /* to ensure that the last deal with SPL_API_DO_DELCON message */
+ int i;
+ for (i = 0; i < SPL_MSG_BOX_NUM; ++i)
+ {
+ SBR_MSG_POST(m,
+ ss_get_instance_msg_box(ss_get_bind_thread_index
+ (sbr_get_conn(sk)), i));
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_udp_send
+* Description : udp send
+* Input : sbr_socket_t * sk
+* struct netbuf *buf
+* spl_ip_addr_t* local_ip
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_udp_send(sbr_socket_t * sk, struct spl_netbuf *buf,
+ spl_ip_addr_t * local_ip)
+{
+ data_com_msg *m =
+ sbr_attach_msg(sk, (struct spl_pbuf *) ADDR_SHTOL(buf->p));
+
+ if (!m)
+ {
+ NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_SEND,
+ MSG_ASYN_POST, sk);
+ msg_send_buf *p = (msg_send_buf *) m->buffer;
+ p->local_ip.addr = local_ip->addr;
+ int ret = memcpy_s(&p->addr, sizeof(spl_ip_addr_t), &buf->addr,
+ sizeof(spl_ip_addr_t));
+ if (ret != 0)
+ {
+ NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ sbr_set_sk_io_errno(sk, EINVAL);
+ SBR_MSG_FREE(m);
+ return -1;
+ }
+
+ p->p = buf->p;
+ p->port = buf->port;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST_RET(m, sbr_get_msg_box(sk), ret);
+
+ if (0 == ret)
+ {
+ return 0;
+ }
+ else
+ {
+ NSSBR_LOGERR("post msg failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EAGAIN);
+ return -1;
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_free_recv_buf
+* Description : free recv buf,can't free buf in app
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void sbr_handle_free_recv_buf(sbr_socket_t * sk)
+{
+ data_com_msg *m = sbr_attach_msg(sk,
+ (struct spl_pbuf *)
+ ADDR_SHTOL(sbr_get_fd_share
+ (sk)->recoder.head));
+
+ if (!m)
+ {
+ NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd);
+ return;
+ }
+
+ sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_PBUF_FREE,
+ MSG_ASYN_POST, sk);
+ msg_free_buf *p = (msg_free_buf *) m->buffer;
+ p->extend_member_bit = 0;
+ p->buf = sbr_get_fd_share(sk)->recoder.head;
+ sbr_get_fd_share(sk)->recoder.head = NULL;
+ sbr_get_fd_share(sk)->recoder.tail = NULL;
+ sbr_get_fd_share(sk)->recoder.totalLen = 0;
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+}
+
+void sbr_handle_free_send_buf(sbr_socket_t * sk, struct spl_pbuf *buf)
+{
+ if (buf != NULL)
+ {
+ data_com_msg *m = sbr_attach_msg(sk, buf);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd);
+ return;
+ }
+
+ sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_PBUF_FREE,
+ MSG_ASYN_POST, sk);
+ msg_free_buf *p = (msg_free_buf *) m->buffer;
+ p->extend_member_bit = 0;
+ p->buf = (struct spl_pbuf *) ADDR_LTOSH(buf);
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_shutdown
+* Description : shut down
+* Input : sbr_socket_t * sk
+* u8 how
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_handle_shutdown(sbr_socket_t * sk, u8 how)
+{
+ int err;
+ data_com_msg *m = SBR_MSG_MALLOC(sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_CLOSE,
+ MSG_SYN_POST, sk);
+ msg_close *p = (msg_close *) m->buffer;
+ p->extend_member_bit = 0;
+ p->time_started = sys_now();
+ p->shut = how;
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+ err = sbr_spl_err_to_errno(m->param.err);
+ SBR_MSG_FREE(m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR("handle getsockopt failed]fd=%d,err=%d", sk->fd, err);
+ sbr_set_sk_errno(sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+void sbr_handle_tcp_recv(sbr_socket_t * sk, u32 len, struct spl_pbuf *buf)
+{
+ data_com_msg *m = sbr_attach_msg(sk, buf);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd);
+ return;
+ }
+
+ sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_RECV,
+ MSG_ASYN_POST, sk);
+ msg_recv_buf *p = (msg_recv_buf *) m->buffer;
+ p->extend_member_bit = 0;
+ p->len = len;
+ p->p = (struct spl_pbuf *) ADDR_LTOSH(buf);
+ SBR_MSG_POST(m, sbr_get_msg_box(sk));
+}
+
+int
+sbr_handle_tcp_send(sbr_socket_t * sk, size_t size, struct spl_pbuf *buf,
+ u8 api_flag)
+{
+ int ret;
+ data_com_msg *m = sbr_attach_msg(sk, buf);
+
+ if (!m)
+ {
+ NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_WRITE,
+ MSG_ASYN_POST, sk);
+ msg_write_buf *p = (msg_write_buf *) m->buffer;
+ p->extend_member_bit = 0;
+ p->len = size;
+ p->p = (struct spl_pbuf *) ADDR_LTOSH(buf);
+ p->apiflags = api_flag;
+ SBR_MSG_POST_RET(m, sbr_get_msg_box(sk), ret);
+
+ if (0 == ret)
+ {
+ return 0;
+ }
+ else
+ {
+ NSSBR_LOGERR("post msg failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EAGAIN);
+ return -1;
+ }
+}
+
+/* need delete sbr_handle_app_touch */
+void sbr_handle_app_touch(void)
+{
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h
new file mode 100644
index 0000000..a659650
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h
@@ -0,0 +1,78 @@
+/*
+*
+* 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 STACKX_MSG_HANDLER_H
+#define STACKX_MSG_HANDLER_H
+#include "stackx_socket.h"
+#include "stackx_ip_addr.h"
+#include "stackx_netbuf.h"
+#include "stackx_spl_share.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define SBR_GET_SOCK_NAME 1
+#define SBR_GET_PEER_NAME 0
+
+int sbr_handle_socket(sbr_socket_t * sk, spl_netconn_type_t type, u8 proto);
+
+int sbr_handle_bind(sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port);
+
+int sbr_handle_listen(sbr_socket_t * sk, int backlog);
+
+int sbr_handle_connect(sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port,
+ spl_ip_addr_t * local_ip);
+
+int sbr_handle_get_name(sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen, u8 cmd);
+
+int sbr_handle_setsockopt(sbr_socket_t * sk, int level, int optname,
+ const void *optval, socklen_t optlen);
+
+int sbr_handle_getsockopt(sbr_socket_t * sk, int level, int optname,
+ void *optval, socklen_t * optlen);
+
+int sbr_handle_close(sbr_socket_t * sk, u8 how);
+
+int sbr_handle_udp_send(sbr_socket_t * sk, struct spl_netbuf *buf,
+ spl_ip_addr_t * local_ip);
+
+void sbr_handle_free_recv_buf(sbr_socket_t * sk);
+
+void sbr_handle_free_send_buf(sbr_socket_t * sk, struct spl_pbuf *buf);
+
+int sbr_handle_shutdown(sbr_socket_t * sk, u8 how);
+
+void sbr_handle_tcp_recv(sbr_socket_t * sk, u32 len, struct spl_pbuf *buf);
+
+int sbr_handle_tcp_send(sbr_socket_t * sk, size_t size, struct spl_pbuf *buf,
+ u8 api_flag);
+
+int sbr_handle_custom_send(sbr_socket_t * sk, struct spl_pbuf *buf,
+ spl_ip_addr_t * src, spl_ip_addr_t * dst, u8 tos);
+
+int sbr_handle_custom_close(sbr_socket_t * sk, spl_ip_addr_t * addr);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c
new file mode 100644
index 0000000..18588a1
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c
@@ -0,0 +1,670 @@
+/*
+*
+* 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 <string.h>
+#include <time.h>
+#include "stackx_msg_handler.h"
+#include "stackx_prot_com.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_err.h"
+#include "nstack_securec.h"
+#include "nsfw_rti.h"
+//#include "stackx_custom.h"
+
+#define FAST_SLEEP_TIME 10000
+#define FAST_RETRY_COUNT 100
+#define MAX_WAIT_TIMEOUT 0x7FFFFFFF
+
+/*****************************************************************************
+* Prototype : sbr_getsockopt_sol_socket
+* Description : get sol socket
+* Input : sbr_socket_t * sk
+* int optname
+* void * optval
+* socklen_t optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_getsockopt_sol_socket(sbr_socket_t * sk, int optname, void *optval,
+ socklen_t optlen)
+{
+ int err = 0;
+
+ switch (optname)
+ {
+ case SO_ERROR:
+ {
+ if (optlen < sizeof(int))
+ {
+ return EINVAL;
+ }
+
+ /* only overwrite ERR_OK or tempoary errors */
+ err = sbr_get_sk_errno(sk);
+
+ if ((0 == err) || (EINPROGRESS == err))
+ {
+ err =
+ sbr_spl_err_to_errno(ss_get_last_errno
+ (sbr_get_conn(sk)));
+ sbr_set_sk_errno(sk, err);
+ }
+ else
+ {
+ sbr_set_sk_errno(sk, 0);
+ }
+
+ *(int *) optval = sbr_get_sk_errno(sk);
+
+ return 0;
+ }
+ case SO_BROADCAST:
+ case SO_KEEPALIVE:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ case SO_REUSEADDR:
+ if (optlen < sizeof(int))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ case SO_RCVTIMEO:
+ case SO_SNDTIMEO:
+ if (optlen < sizeof(struct timeval))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ case SO_LINGER:
+ if (optlen < sizeof(struct linger))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/*****************************************************************************
+* Prototype : sbr_getsockopt_ipproto_ip
+* Description : get ipproto ip
+* Input : int optname
+* void * optval
+* socklen_t optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_getsockopt_ipproto_ip(int optname, void *optval, socklen_t optlen)
+{
+ int err = 0;
+
+ switch (optname)
+ {
+ case IP_TOS:
+ if (optlen < sizeof(u8))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/*****************************************************************************
+* Prototype : sbr_pick_timeout
+* Description : pick time
+* Input : const void * optval
+* socklen_t optlen
+* i32* timeout
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_pick_timeout(const void *optval, socklen_t optlen, i32 * timeout)
+{
+ if (optlen < sizeof(struct timeval))
+ {
+ return EINVAL;
+ }
+
+ struct timeval *time_val = (struct timeval *) optval;
+ if ((time_val->tv_usec < 0) || (time_val->tv_usec > USEC_TO_SEC))
+ {
+ return EDOM;
+ }
+ else
+ {
+ if (time_val->tv_sec < 0)
+ {
+ *timeout = 0;
+ }
+ else
+ {
+ *timeout = MAX_WAIT_TIMEOUT;
+ if ((time_val->tv_sec != 0) || (time_val->tv_usec != 0))
+ {
+ if (time_val->tv_sec < ((MAX_WAIT_TIMEOUT / 1000) - 1))
+ {
+ *timeout =
+ time_val->tv_sec * 1000 + time_val->tv_usec / 1000;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_setsockopt_sol_socket
+* Description : set sol socket
+* Input : sbr_socket_t * sk
+* int optname
+* const void * optval
+* socklen_t optlen
+* netconn_type_t type
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_setsockopt_sol_socket(sbr_socket_t * sk, int optname, const void *optval,
+ socklen_t optlen, spl_netconn_type_t type)
+{
+ int err = 0;
+
+ switch (optname)
+ {
+ case SO_REUSEADDR:
+ case SO_BROADCAST:
+ case SO_KEEPALIVE:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ if (optlen < sizeof(int))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ case SO_RCVTIMEO:
+ err =
+ sbr_pick_timeout(optval, optlen,
+ &sbr_get_fd_share(sk)->recv_timeout);
+ break;
+ case SO_SNDTIMEO:
+ err =
+ sbr_pick_timeout(optval, optlen,
+ &sbr_get_fd_share(sk)->send_timeout);
+ break;
+ case SO_LINGER:
+ if (optlen < sizeof(struct linger))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/*****************************************************************************
+* Prototype : sbr_setsockopt_ipproto_ip
+* Description : set ipproto ip
+* Input : int optname
+* const void * optval
+* socklen_t optlen
+* netconn_type_t type
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_setsockopt_ipproto_ip(int optname, const void *optval, socklen_t optlen,
+ spl_netconn_type_t type)
+{
+ int err = 0;
+
+ switch (optname)
+ {
+ case IP_TOS:
+ if (optlen < sizeof(u8))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ case IP_MULTICAST_TTL:
+ if (optlen < sizeof(u8))
+ {
+ err = EINVAL;
+ break;
+ }
+
+ if (type != SPL_NETCONN_UDP)
+ {
+ err = EAFNOSUPPORT;
+ break;
+ }
+
+ break;
+ case IP_MULTICAST_IF:
+ if (optlen < sizeof(struct in_addr))
+ {
+ err = EINVAL;
+ break;
+ }
+
+ if (type != SPL_NETCONN_UDP)
+ {
+ err = EAFNOSUPPORT;
+ break;
+ }
+
+ break;
+ case IP_MULTICAST_LOOP:
+ if (optlen < sizeof(u8))
+ {
+ err = EINVAL;
+ break;
+ }
+
+ if (type != SPL_NETCONN_UDP)
+ {
+ err = EAFNOSUPPORT;
+ break;
+ }
+
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/*****************************************************************************
+* Prototype : sbr_dequeue_buf
+* Description : dequeue buf
+* Input : sbr_socket_t * sk
+* void **buf
+* i32 timeout
+* u8 use_l4_ring
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_dequeue_buf(sbr_socket_t * sk, void **buf, i32 timeout)
+{
+ mring_handle ring = ss_get_recv_ring(sbr_get_conn(sk));
+
+ struct timespec start, end;
+ long timediff;
+ long timediff_sec;
+ long timeout_sec = (long) (timeout / 1000);
+ unsigned int retry_count = 0;
+
+ if (timeout > 0)
+ {
+ if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &start)))
+ {
+ NSSBR_LOGERR("Failed to get time, errno = %d", errno);
+ }
+ }
+
+ if (!ss_recv_ring_valid(sbr_get_conn(sk)))
+ {
+ NSSBR_LOGDBG("ring is invalid]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, ENOTCONN);
+ return -1;
+ }
+
+ int dequeue_ret = 0;
+ pid_t pid = get_sys_pid();
+
+ while (1)
+ {
+ if (ss_is_shut_rd(sbr_get_conn(sk)))
+ {
+ NSSBR_LOGDBG("is shut rd]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EINVAL);
+ return -1;
+ }
+
+ dequeue_ret = nsfw_mem_ring_dequeue(ring, buf);
+ if (1 == dequeue_ret)
+ {
+ pbuf_set_recycle_flg((struct spl_pbuf *) *buf, pid); /*release buf hold by app on abnormal exit */
+ return 0;
+ }
+ else if (0 == dequeue_ret)
+ {
+ /*If the peer reset connect, try to receive data only once */
+ if (ss_can_not_recv(sbr_get_conn(sk)))
+ {
+ NS_LOG_CTRL(LOG_CTRL_RECV_QUEUE_FULL, LOGSBR, "NSSBR",
+ NSLOG_WAR, "try to fetch one more time]fd=%d",
+ sk->fd);
+ /**
+ * l4_ring will not be processed here as can_not_recv flag is
+ * set by TCP only.
+ */
+ if (1 == nsfw_mem_ring_dequeue(ring, buf))
+ {
+ pbuf_set_recycle_flg((struct spl_pbuf *) *buf, pid);
+ return 0;
+ }
+
+ sbr_set_sk_io_errno(sk, ENOTCONN);
+ return -1;
+ }
+
+ int err = ss_get_last_errno(sbr_get_conn(sk));
+ if (SPL_ERR_IS_FATAL(err) || err == ERR_TIMEOUT) /* have to handle ERR_TIMEOUT here, when TCP keepalive timeout. */
+ {
+ NS_LOG_CTRL(LOG_CTRL_RECV_QUEUE_FULL, LOGSBR, "NSSBR",
+ NSLOG_ERR, "connection fatal error!err=%d", err);
+
+ /* l4_ring need to be handled in the future */
+ if (1 == nsfw_mem_ring_dequeue(ring, buf))
+ {
+ pbuf_set_recycle_flg((struct spl_pbuf *) *buf, pid);
+ return 0;
+ }
+
+ sbr_set_sk_io_errno(sk, sbr_spl_err_to_errno(err));
+ return -1;
+ }
+
+ if (0 > timeout)
+ {
+ sbr_set_sk_io_errno(sk, EWOULDBLOCK);
+ return -1;
+ }
+
+ if (retry_count < FAST_RETRY_COUNT)
+ {
+ sys_sleep_ns(0, FAST_SLEEP_TIME);
+ retry_count++;
+ }
+ else
+ {
+ sys_sleep_ns(0, sbr_get_fd_share(sk)->block_polling_time);
+ }
+
+ if (timeout > 0)
+ {
+ if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &end)))
+ {
+ NSSBR_LOGERR("Failed to get time, errno = %d", errno);
+ }
+ timediff_sec = end.tv_sec - start.tv_sec;
+ if (timediff_sec >= timeout_sec)
+ {
+ timediff = end.tv_nsec > start.tv_nsec ?
+ (timediff_sec * 1000) + (end.tv_nsec -
+ start.tv_nsec) /
+ USEC_TO_SEC : (timediff_sec * 1000) -
+ ((start.tv_nsec - end.tv_nsec) / USEC_TO_SEC);
+ if (timediff > timeout)
+ {
+ NSSBR_LOGDBG("recv timeout]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EWOULDBLOCK);
+ return -1;
+ }
+ }
+ }
+ }
+ else
+ {
+ NSSBR_LOGERR("dequeue failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EINVAL);
+ return -1;
+ }
+ }
+}
+
+int sbr_com_peak(sbr_socket_t * sk)
+{
+ NSSBR_LOGERR("not implement]fd=%d", sk->fd);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_try_lock_recv
+* Description : try lock recv
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_com_try_lock_recv(sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ return common_spinlock_try_lock_with_pid(&sbr_get_fd_share(sk)->recv_lock,
+ get_sys_pid());
+#else
+ return 1;
+#endif
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_lock_common
+* Description : lock common
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void sbr_com_lock_common(sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ while (!common_spinlock_try_lock_with_pid
+ (&sbr_get_fd_share(sk)->common_lock, get_sys_pid()))
+ {
+ sys_sleep_ns(0, 0);
+ }
+#endif
+
+}
+
+void sbr_com_fork_parent(sbr_socket_t * sk, pid_t p)
+{
+ i32 ref = ss_inc_fork_ref(sbr_get_conn(sk));
+ NSSBR_LOGINF
+ ("inc fork ref] fd=%d, p=%d, ref=%d, conn=%p, private_data=%p",
+ sk->fd, p, ref, sbr_get_conn(sk), sbr_get_conn(sk)->private_data);
+}
+
+void sbr_com_fork_child(sbr_socket_t * sk, pid_t p, pid_t c)
+{
+ if (ss_add_pid(sbr_get_conn(sk), c) != 0)
+ {
+ NSSBR_LOGERR
+ ("add pid failed] fd=%d, p=%d, c=%d, ref=%d, conn=%p, private_data=%p",
+ sk->fd, p, c, ss_get_fork_ref(sbr_get_conn(sk)),
+ sbr_get_conn(sk), sbr_get_conn(sk)->private_data);
+ }
+ else
+ {
+ NSSBR_LOGINF
+ ("add pid ok] fd=%d, p=%d, c=%d, ref=%d, conn=%p, private_data=%p",
+ sk->fd, p, c, ss_get_fork_ref(sbr_get_conn(sk)),
+ sbr_get_conn(sk), sbr_get_conn(sk)->private_data);
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_unlock_common
+* Description : unlock common
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void sbr_com_unlock_common(sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ common_spinlock_unlock(&sbr_get_fd_share(sk)->common_lock);
+#endif
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_free_recv_buf
+* Description : free recv buf,can't free buf in app
+* Input : sbr_socket_t * sk
+* struct spl_pbuf *p
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void sbr_com_free_recv_buf(sbr_socket_t * sk, struct spl_pbuf *p)
+{
+ struct spl_pbuf *p_orig = p;
+ if (p)
+ {
+ p->freeNext = NULL;
+ p = (struct spl_pbuf *) ADDR_LTOSH(p);
+
+ if (sbr_get_fd_share(sk)->recoder.totalLen > 0)
+ {
+ ((struct spl_pbuf *)
+ ADDR_SHTOL(sbr_get_fd_share(sk)->recoder.tail))->freeNext = p;
+ sbr_get_fd_share(sk)->recoder.tail = p;
+ }
+ else
+ {
+ sbr_get_fd_share(sk)->recoder.head = p;
+ sbr_get_fd_share(sk)->recoder.tail = p;
+ }
+
+ sbr_get_fd_share(sk)->recoder.totalLen++;
+ }
+
+ /* send MSG only if it's a big packet or number of packets larger than 32 */
+ if ((p_orig && p_orig->tot_len > MAX_RECV_FREE_LEN) ||
+ (sbr_get_fd_share(sk)->recoder.totalLen >= MAX_RECV_FREE_BUF))
+ {
+ sbr_handle_free_recv_buf(sk);
+ }
+
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_sockaddr_and_len
+* Description : get addr and len
+* Input : u16 port
+* spl_ip_addr_t * ipaddr
+* struct sockaddr * addr
+* socklen_t * addrlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_get_sockaddr_and_len(u16 port, spl_ip_addr_t * ipaddr,
+ struct sockaddr *addr, socklen_t * addrlen)
+{
+ int ret;
+ struct sockaddr_in sin;
+
+ ret = memset_s(&sin, sizeof(sin), 0, sizeof(sin));
+ if (0 != ret)
+ {
+ NSSBR_LOGERR("MEMSET_S failed]ret=%d.", ret);
+ return -1;
+ }
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ inet_addr_from_ipaddr(&sin.sin_addr, ipaddr);
+ if (*addrlen > sizeof(struct sockaddr))
+ {
+ *addrlen = sizeof(struct sockaddr);
+ }
+
+ if (*addrlen > 0)
+ {
+ ret = memcpy_s(addr, sizeof(struct sockaddr), &sin, *addrlen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR("MEMCPY_S failed]ret=%d", ret);
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_set_app_info
+* Description : set app info to netconn
+* Input : sbr_socket_t * sk
+* void* appinfo
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void sbr_com_set_app_info(sbr_socket_t * sk, void *appinfo)
+{
+ return;
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h
new file mode 100644
index 0000000..4d542fd
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h
@@ -0,0 +1,159 @@
+/*
+*
+* 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 STACKX_PROT_COM_H
+#define STACKX_PROT_COM_H
+#include "stackx_socket.h"
+#include "stackx_ip_addr.h"
+#include "stackx_res_mgr.h"
+#include "stackx_pbuf.h"
+#include "stackx_macro.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define MAX_RECV_FREE_BUF 32
+#define MAX_RECV_FREE_LEN (SPL_FRAME_MTU - SPL_IP_HLEN)
+#define USEC_TO_SEC 1000000
+
+#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 sbr_malloc_tx_pbuf(len, offset) sbr_malloc_pbuf(sbr_get_tx_pool(), len, TX_MBUF_MAX_LEN, offset)
+
+static inline int sbr_spl_err_to_errno(i32 err)
+{
+ static int table[] = {
+ 0, /* ERR_OK 0 No error, everything OK. */
+ ENOMEM, /* ERR_MEM -1 Out of memory error. */
+ ENOBUFS, /* ERR_BUF -2 Buffer error. */
+ ETIMEDOUT, /* ERR_TIMEOUT -3 Timeout */
+ EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
+ EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
+ EINVAL, /* ERR_VAL -6 Illegal value. */
+ EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
+ EADDRINUSE, /* ERR_USE -8 Address in use. */
+ EISCONN, /* ERR_ISCONN -9 Already connected. */
+ ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
+ ECONNRESET, /* ERR_RST -11 Connection reset. */
+ ENOTCONN, /* ERR_CLSD -12 Connection closed. */
+ ENOTCONN, /* ERR_CONN -13 Not connected. */
+ EIO, /* ERR_ARG -14 Illegal argument. */
+ -1, /* ERR_IF -15 Low-level netif error */
+ EALREADY, /*ERR_ALREADY -16 previous connect attemt has not yet completed */
+ EPROTOTYPE, /*ERR_PROTOTYPE -17 prototype error or some other generic error.
+ the operation is not allowed on current socket */
+ EINVAL, /* ERR_CALLBACK -18 callback error */
+ EADDRNOTAVAIL, /* ERR_CANTASSIGNADDR -19 Cannot assign requested address */
+ EIO, /* ERR_CONTAINER_ID -20 Illegal container id */
+ ENOTSOCK, /*ERR_NOTSOCK -21 not a socket */
+ -1, /* ERR_CLOSE_WAIT -22 closed in established state */
+ EPROTONOSUPPORT, /* ERR_EPROTONOSUPPORT -23 Protocol not supported */
+ ECONNABORTED /* ERR_FAULTRECOVERY -24 SPL just recovered from a fatal fault */
+ };
+
+ if (((-(err)) >= 0)
+ && (-(err)) < (i32) (sizeof(table) / sizeof(table[0])))
+ {
+ return table[-(err)];
+ }
+ else
+ {
+ return EIO;
+ }
+}
+
+int sbr_getsockopt_sol_socket(sbr_socket_t * sk, int optname, void *optval,
+ socklen_t optlen);
+int sbr_getsockopt_ipproto_ip(int optname, void *optval, socklen_t optlen);
+int sbr_setsockopt_sol_socket(sbr_socket_t * sk, int optname,
+ const void *optval, socklen_t optlen,
+ spl_netconn_type_t type);
+int sbr_setsockopt_ipproto_ip(int optname, const void *optval,
+ socklen_t optlen, spl_netconn_type_t type);
+int sbr_dequeue_buf(sbr_socket_t * sk, void **buf, i32 timeout);
+int sbr_com_peak(sbr_socket_t * sk);
+int sbr_com_try_lock_recv(sbr_socket_t * sk);
+/*****************************************************************************
+* Prototype : sbr_com_lock_recv
+* Description : lock recv
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void sbr_com_lock_recv(sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ while (!common_spinlock_try_lock_with_pid
+ (&sbr_get_fd_share(sk)->recv_lock, get_sys_pid()))
+ {
+ sys_sleep_ns(0, 0);
+ }
+#endif
+
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_unlock_recv
+* Description : unlock recv
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void sbr_com_unlock_recv(sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ common_spinlock_unlock(&sbr_get_fd_share(sk)->recv_lock);
+#endif
+}
+
+void sbr_com_lock_common(sbr_socket_t * sk);
+void sbr_com_unlock_common(sbr_socket_t * sk);
+void sbr_com_free_recv_buf(sbr_socket_t * sk, struct spl_pbuf *p);
+int sbr_get_sockaddr_and_len(u16 port, spl_ip_addr_t * ip_addr,
+ struct sockaddr *addr, socklen_t * addrlen);
+void sbr_com_set_app_info(sbr_socket_t * sk, void *appinfo);
+
+void sbr_com_fork_parent(sbr_socket_t * sk, pid_t p);
+void sbr_com_fork_child(sbr_socket_t * sk, pid_t p, pid_t c);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c b/stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c
new file mode 100644
index 0000000..dbcb4e3
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c
@@ -0,0 +1,109 @@
+/*
+*
+* 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 "sbr_protocol_api.h"
+#include "stackx_epoll_api.h"
+#include "stackx_socket.h"
+#include "stackx_res_mgr.h"
+#include "stackx_common_opt.h"
+#include "common_mem_api.h"
+#include "stackx_event.h"
+
+extern sbr_fdopt tcp_fdopt;
+extern sbr_fdopt udp_fdopt;
+extern sbr_fdopt raw_fdopt;
+extern sbr_fdopt custom_fdopt;
+
+/*****************************************************************************
+* Prototype : sbr_init_protocol
+* Description : init protocol
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_init_protocol()
+{
+ return sbr_init_stackx();
+}
+
+/*****************************************************************************
+* Prototype : sbr_fork_protocol
+* Description : init protocol
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_fork_protocol()
+{
+ pid_t pid = updata_sys_pid();
+
+ NSSBR_LOGINF("update pid in child]pid=%d", pid);
+ return sbr_fork_stackx();
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_fdopt
+* Description : get fdopt by domain type protocol
+* Input : int domain
+* int type
+* int protocol
+* Output : None
+* Return Value : sbr_fdopt*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+sbr_fdopt *sbr_get_fdopt(int domain, int type, int protocol)
+{
+ if (domain != AF_INET)
+ {
+ NSSBR_LOGERR("domain is not AF_INET]domain=%d", domain);
+ sbr_set_errno(EAFNOSUPPORT);
+ return NULL;
+ }
+
+ sbr_fdopt *fdopt = NULL;
+
+ switch (type & (~(O_NONBLOCK | SOCK_CLOEXEC)))
+ {
+ case SOCK_DGRAM:
+ fdopt = &udp_fdopt;
+ break;
+ case SOCK_STREAM:
+ fdopt = &tcp_fdopt;
+ break;
+
+ default:
+ NSSBR_LOGDBG("type is unknown]type=%d", type);
+ sbr_set_errno(ESOCKTNOSUPPORT);
+ return NULL;
+ }
+
+ return fdopt;
+}
+
+/* app send its version info to nStackMain */
+extern void sbr_handle_app_touch(void);
+void sbr_app_touch_in(void)
+{
+ sbr_handle_app_touch();
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c
new file mode 100644
index 0000000..964a1f9
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c
@@ -0,0 +1,271 @@
+/*
+*
+* 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 "stackx_res_mgr.h"
+#include "stackx_common.h"
+#include "nstack_securec.h"
+#include "nsfw_msg.h"
+#include "stackx_common.h"
+#include "nsfw_mgr_com_api.h"
+#include "stackx_cfg.h"
+#include "nsfw_maintain_api.h"
+//#include "stackx_dfx_api.h"
+#include "stackx_app_res.h"
+
+sbr_share_group g_share_group = { 0 };
+
+#define SLOW_SLEEP_TIME 500000
+
+NSTACK_STATIC inline void sbr_reset_fd_share(sbr_fd_share * fd_share)
+{
+ common_mem_spinlock_init(&fd_share->recv_lock);
+ common_mem_spinlock_init(&fd_share->common_lock);
+ fd_share->err = 0;
+ fd_share->lastoffset = 0;
+ fd_share->lastdata = NULL;
+ fd_share->recoder.head = NULL;
+ fd_share->recoder.tail = NULL;
+ fd_share->recoder.totalLen = 0;
+ fd_share->recv_timeout = 0;
+ fd_share->send_timeout = 0;
+ fd_share->rcvlowat = 1;
+ fd_share->block_polling_time = SLOW_SLEEP_TIME;
+}
+
+/*****************************************************************************
+* Prototype : sbr_init_tx_pool
+* Description : get tx buf pool
+* Input : None
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC int sbr_init_tx_pool()
+{
+ mpool_handle pool[1];
+ pool[0] = NULL;
+
+ (void) sbr_malloc_tx_pool(get_sys_pid(), pool, 1);
+ if (pool[0])
+ {
+ g_share_group.tx_pool = pool[0];
+ return 0;
+ }
+
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_init_app_res
+* Description : get msg, conn pool
+* Input : None
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC int sbr_init_app_res()
+{
+ g_share_group.conn_pool = sbr_get_instance_conn_pool(0);
+ if (!g_share_group.conn_pool)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*=========== get share config for app =============*/
+NSTACK_STATIC inline int get_share_config()
+{
+ static nsfw_mem_name g_cfg_mem_info =
+ { NSFW_SHMEM, NSFW_PROC_MAIN, NSTACK_SHARE_CONFIG };
+
+ mzone_handle base_cfg_mem = nsfw_mem_zone_lookup(&g_cfg_mem_info);
+ if (NULL == base_cfg_mem)
+ {
+ NSSOC_LOGERR("get config share mem failed.");
+ return -1;
+ }
+
+ if (get_share_cfg_from_mem(base_cfg_mem) < 0)
+ {
+ NSSOC_LOGERR("get share config failed.");
+ return -1;
+ }
+
+ NSSOC_LOGDBG("get share config success.");
+ return 0;
+}
+
+int nstack_set_share_config()
+{
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_init_stackx
+* Description : init stackx res
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_init_stackx()
+{
+ sbr_init_cfg();
+ if (get_share_config() < 0)
+ {
+ NSSBR_LOGERR("get_share_config failed");
+ return -1;
+ }
+
+ if (sbr_attach_group_array() != 0)
+ {
+ NSSBR_LOGERR("sbr_attach_group_array failed");
+ return -1;
+ }
+
+ NSSBR_LOGDBG("sbr_attach_group_array ok");
+
+ if (sbr_init_tx_pool() != 0)
+ {
+ NSSBR_LOGERR("init tx pool failed");
+ return -1;
+ }
+
+ NSSBR_LOGDBG("init tx pool ok");
+
+ if (sbr_init_app_res() != 0)
+ {
+ NSSBR_LOGERR("sbr_init_app_res failed");
+ return -1;
+ }
+
+ NSSBR_LOGDBG("sbr_init_app_res ok");
+ NSSBR_LOGDBG("sbr_init_stackx ok");
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_fork_stackx
+* Description : init stackx res
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_fork_stackx()
+{
+
+ if (sbr_attach_group_array() != 0)
+ {
+ NSSBR_LOGERR("sbr_attach_group_array failed");
+ return -1;
+ }
+
+ NSSBR_LOGDBG("sbr_attach_group_array ok");
+
+ if (sbr_init_tx_pool() != 0)
+ {
+ NSSBR_LOGERR("init tx pool failed");
+ return -1;
+ }
+
+ NSSBR_LOGDBG("init tx pool ok");
+ NSSBR_LOGDBG("sbr_fork_stackx ok");
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_malloc_conn_for_sk
+* Description : malloc netconn for sk,need add pid
+* Input : sbr_socket_t* sk
+* netconn_type_t type
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_malloc_conn_for_sk(sbr_socket_t * sk, spl_netconn_type_t type)
+{
+ spl_netconn_t *conn = ss_malloc_conn_app(g_share_group.conn_pool, type);
+
+ if (!conn)
+ {
+ NSSBR_LOGERR("malloc conn failed]fd=%d", sk->fd);
+ sbr_set_errno(ENOBUFS);
+ return -1;
+ }
+
+ NSSBR_LOGINF("malloc conn ok]fd=%d,conn=%p", sk->fd, conn);
+
+ u16 thread_index = 0;
+ ss_set_bind_thread_index(conn, thread_index);
+ ss_set_msg_box(conn, ss_get_instance_msg_box(thread_index, 0));
+
+ sbr_fd_share *fd_share =
+ (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE);
+ sbr_reset_fd_share(fd_share);
+
+ sk->stack_obj = (void *) conn;
+ sk->sk_obj = (void *) fd_share;
+ return 0;
+}
+
+int sbr_init_conn_for_accept(sbr_socket_t * sk, spl_netconn_t * conn)
+{
+ if (!conn)
+ {
+ sbr_set_sk_errno(sk, ENOBUFS);
+ return -1;
+ }
+
+ NSSBR_LOGINF("accept conn ok]fd=%d,conn=%p,private_data=%p", sk->fd, conn,
+ conn->private_data);
+
+ if (ss_add_pid(conn, get_sys_pid()) < 0)
+ {
+ NSSBR_LOGERR("ss_add_pid failed]fd=%d", sk->fd);
+ }
+
+ ss_set_accept_from(conn, NULL); /* need clear flag */
+
+ sbr_fd_share *fd_share =
+ (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE);
+ sbr_reset_fd_share(fd_share);
+
+ sk->stack_obj = (void *) conn;
+ sk->sk_obj = (void *) fd_share;
+
+ return 0;
+}
+
+void sbr_free_conn_from_sk(sbr_socket_t * sk)
+{
+ ss_free_conn(sbr_get_conn(sk));
+ sk->stack_obj = NULL;
+ sk->sk_obj = NULL;
+ NSSBR_LOGDBG("free conn ok]fd=%d", sk->fd);
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h
new file mode 100644
index 0000000..6fa6501
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h
@@ -0,0 +1,67 @@
+/*
+*
+* 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 STACKX_RES_MGR_H
+#define STACKX_RES_MGR_H
+#include "stackx_socket.h"
+#include "stackx_ip_tos.h"
+#include "stackx_tx_box.h"
+#include "stackx_app_res.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef struct
+{
+ mring_handle conn_pool;
+ mpool_handle tx_pool;
+} sbr_share_group;
+
+extern sbr_share_group g_share_group;
+
+static inline mpool_handle sbr_get_tx_pool()
+{
+ return g_share_group.tx_pool;
+}
+
+static inline mring_handle sbr_get_conn_pool()
+{
+ return (mring_handle) ADDR_LTOSH(g_share_group.conn_pool);
+}
+
+static inline mring_handle sbr_get_spl_msg_box(sbr_socket_t * sk, u8 tos)
+{
+ return
+ ss_get_instance_msg_box(ss_get_bind_thread_index(sbr_get_conn(sk)),
+ stackx_get_prio(tos));
+}
+
+int sbr_init_stackx();
+int sbr_fork_stackx();
+int sbr_malloc_conn_for_sk(sbr_socket_t * sk, spl_netconn_type_t type);
+int sbr_init_conn_for_accept(sbr_socket_t * sk, spl_netconn_t * conn);
+void sbr_free_conn_from_sk(sbr_socket_t * sk);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_socket.h b/stacks/lwip_stack/lwip_src/socket/stackx_socket.h
new file mode 100644
index 0000000..edc0e86
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_socket.h
@@ -0,0 +1,138 @@
+/*
+*
+* 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 STACKX_SOCKET_H
+#define STACKX_SOCKET_H
+#include "sbr_protocol_api.h"
+#include "stackx_spl_share.h"
+#include "nstack_log.h"
+#include "stackx_pbuf.h"
+#include "common_mem_spinlock.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef struct
+{
+ PRIMARY_ADDR struct spl_pbuf *head;
+ PRIMARY_ADDR struct spl_pbuf *tail;
+ int totalLen;
+} sbr_recvbuf_recoder;
+
+/* need fork and recycle */
+typedef struct
+{
+ common_mem_spinlock_t recv_lock;
+ common_mem_spinlock_t common_lock;
+ PRIMARY_ADDR void *lastdata;
+ u32 lastoffset;
+ sbr_recvbuf_recoder recoder;
+ i32 recv_timeout;
+ i32 send_timeout;
+ i32 rcvlowat;
+ int err;
+ u64 block_polling_time;
+ i64 extend_member_bit;
+} sbr_fd_share;
+
+/* check sbr_fd_share size */
+SIZE_OF_TYPE_NOT_LARGER_THAN_RETURN(sbr_fd_share, SBR_FD_SIZE);
+
+#define sbr_get_fd_share(sk) ((sbr_fd_share*)sk->sk_obj)
+
+#define sbr_get_conn(sk) ((spl_netconn_t*)sk->stack_obj)
+
+#define sbr_get_msg_box(sk) ss_get_msg_box(sbr_get_conn(sk))
+
+/*****************************************************************************
+* Prototype : sbr_set_sk_errno
+* Description : set errno for sk
+* Input : sbr_socket_t * sk
+* int err
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void sbr_set_sk_errno(sbr_socket_t * sk, int err)
+{
+ sbr_get_fd_share(sk)->err = err;
+ if (err != 0)
+ {
+ if (sbr_get_conn(sk))
+ {
+ NSSBR_LOGERR("fd=%d,errno=%d,conn=%p,private_data=%p", sk->fd,
+ err, sbr_get_conn(sk),
+ ss_get_private_data(sbr_get_conn(sk)));
+ }
+
+ sbr_set_errno(err);
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_set_sk_io_errno
+* Description : set errno for sk in send/recv func, in case of too many logs
+* Input : sbr_socket_t * sk
+* int err
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void sbr_set_sk_io_errno(sbr_socket_t * sk, int err)
+{
+ sbr_get_fd_share(sk)->err = err;
+ if (err != 0)
+ {
+ if (sbr_get_conn(sk))
+ {
+ NSSBR_LOGDBG("fd=%d,errno=%d,conn=%p,private_data=%p", sk->fd,
+ err, sbr_get_conn(sk),
+ ss_get_private_data(sbr_get_conn(sk)));
+ }
+
+ sbr_set_errno(err);
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_sk_errno
+* Description : get sk's errno
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int sbr_get_sk_errno(sbr_socket_t * sk)
+{
+ return sbr_get_fd_share(sk)->err;
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_tcp.c b/stacks/lwip_stack/lwip_src/socket/stackx_tcp.c
new file mode 100644
index 0000000..4bc5317
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_tcp.c
@@ -0,0 +1,1682 @@
+/*
+*
+* 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 "stackx_prot_com.h"
+#include "stackx_msg_handler.h"
+#include "stackx_pbuf.h"
+#include "stackx_epoll_api.h"
+#include "nstack_securec.h"
+#include "common_pal_bitwide_adjust.h"
+#include "common_mem_mbuf.h"
+#include "stackx_spl_share.h"
+#include "stackx_err.h"
+#include "stackx_cfg.h"
+#include "spl_opt.h"
+//#include "stackx_tcp_sctl.h"
+#include "stackx_tcp_opt.h"
+//#include "stackx_dfx_api.h"
+#include "stackx_spl_msg.h"
+#ifdef HAL_LIB
+#else
+#include "rte_memcpy.h"
+#endif
+
+static void sbr_tcp_init_conn(spl_netconn_t * conn)
+{
+ conn->tcp_sndbuf = CONN_TCP_MEM_DEF_LINE;
+ conn->conn_pool = sbr_get_conn_pool();
+}
+
+/* need close after accept failed */
+static void sbr_tcp_accept_failed(sbr_socket_t * sk)
+{
+ (void) sbr_handle_close(sk, 0);
+ sk->stack_obj = NULL;
+ sk->sk_obj = NULL;
+}
+
+NSTACK_STATIC int
+sbr_tcp_socket(sbr_socket_t * sk, int domain, int type, int protocol)
+{
+ int err = 0;
+
+ if (sbr_malloc_conn_for_sk(sk, SPL_NETCONN_TCP) != 0)
+ {
+ return -1;
+ }
+
+ sbr_tcp_init_conn(sbr_get_conn(sk));
+
+ err = sbr_handle_socket(sk, SPL_NETCONN_TCP, 0);
+ if (0 == err)
+ {
+ /* Prevent automatic window updates, we do this on our own! */
+ ss_set_noautorecved_flag(sbr_get_conn(sk), 1);
+
+ ss_set_nonblock_flag(sbr_get_conn(sk), (type & O_NONBLOCK));
+
+ ss_add_recv_event(sbr_get_conn(sk));
+
+ ss_set_send_event(sbr_get_conn(sk), 1);
+
+ NSSBR_LOGINF("add write and read events]fd=%d", sk->fd);
+
+ return 0;
+ }
+ else
+ {
+ sbr_free_conn_from_sk(sk);
+ return err;
+ }
+}
+
+NSTACK_STATIC int
+sbr_tcp_bind(sbr_socket_t * sk, const struct sockaddr *name,
+ socklen_t namelen)
+{
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name;
+ NSSBR_LOGINF("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa(addr_in->sin_addr), ntohs(addr_in->sin_port),
+ sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk)));
+ spl_ip_addr_t local_addr;
+ inet_addr_to_ipaddr(&local_addr, &addr_in->sin_addr);
+ u16 local_port = addr_in->sin_port;
+ return sbr_handle_bind(sk, &local_addr, ntohs(local_port));
+}
+
+NSTACK_STATIC int sbr_tcp_listen(sbr_socket_t * sk, int backlog)
+{
+ ss_set_is_listen_conn(sbr_get_conn(sk), 1);
+ return sbr_handle_listen(sk, backlog);
+}
+
+static inline int
+sbr_tcp_recv_is_timeout(sbr_socket_t * sk, struct timespec *starttm)
+{
+ struct timespec currtm;
+ i64 timediff_ms, timediff_sec;
+ i64 timeout_thr_ms, timeout_thr_sec;
+
+ timeout_thr_ms = sbr_get_fd_share(sk)->recv_timeout;
+ if (0 == timeout_thr_ms)
+ {
+ return ERR_OK;
+ }
+
+ timeout_thr_sec = (i64) (timeout_thr_ms / 1000);
+
+ /* Handle system time change side-effects */
+ if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &currtm)))
+ {
+ NSSBR_LOGERR("Failed to get time, errno = %d", errno);
+ }
+
+ timediff_sec = currtm.tv_sec - starttm->tv_sec;
+ if (timediff_sec >= timeout_thr_sec)
+ {
+ timediff_ms = currtm.tv_nsec > starttm->tv_nsec ?
+ (timediff_sec * 1000) + (currtm.tv_nsec -
+ starttm->tv_nsec) /
+ USEC_TO_SEC : (timediff_sec * 1000) -
+ ((starttm->tv_nsec - currtm.tv_nsec) / USEC_TO_SEC);
+
+ /*NOTE: if user configured the timeout as say 0.5 ms, then timediff value
+ will be negetive if still 0.5 ms is not elapsed. this is intended and we should
+ not typecast to any unsigned type during this below if check */
+ if (timediff_ms > timeout_thr_ms)
+ {
+ sbr_set_sk_errno(sk, ETIMEDOUT);
+ return ETIMEDOUT;
+ }
+ }
+
+ return ERR_OK;
+}
+
+static inline int sbr_tcp_wait_new_conn(sbr_socket_t * sk, void **new_buf)
+{
+ int ret = 0;
+ int elem_num;
+ u32 timeout_thr_sec;
+ struct timespec starttm = { 0, 0 };
+ unsigned int retry_count = 0;
+ mring_handle ring = NULL;
+
+#define FAST_SLEEP_TIME 10000
+#define SLOW_SLEEP_TIME 500000
+#define FAST_RETRY_COUNT 100
+
+ ring = ss_get_recv_ring(sbr_get_conn(sk)); //clear codeDEX warning , CID:24284
+ timeout_thr_sec = sbr_get_fd_share(sk)->recv_timeout / 1000;
+ if (0 != timeout_thr_sec)
+ {
+ if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &starttm)))
+ {
+ NSSBR_LOGERR("Failed to get time, errno = %d", errno);
+ }
+ }
+
+ while (1)
+ {
+ if (ss_is_shut_rd(sbr_get_conn(sk)))
+ {
+ sbr_set_sk_errno(sk, EINVAL);
+ ret = EINVAL;
+ break;
+ }
+
+ elem_num = nsfw_mem_ring_dequeue(ring, new_buf);
+ if (1 == elem_num)
+ {
+ break;
+ }
+ else if (0 == elem_num)
+ {
+ ret = sbr_tcp_recv_is_timeout(sk, &starttm);
+ if (0 != ret)
+ {
+ break;
+ }
+
+ /* reduce CPU usage in blocking mode- Begin */
+ if (retry_count < FAST_RETRY_COUNT)
+ {
+ sys_sleep_ns(0, FAST_SLEEP_TIME);
+ retry_count++;
+ }
+ else
+ {
+ sys_sleep_ns(0, sbr_get_fd_share(sk)->block_polling_time);
+ }
+
+ continue;
+ }
+ else
+ {
+ sbr_set_sk_errno(sk, EINVAL);
+ ret = EINVAL;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+NSTACK_STATIC inline int
+sbr_tcp_get_sockaddr(sbr_socket_t * sk, struct sockaddr *addr,
+ socklen_t * addrlen)
+{
+ int ret;
+ spl_netconn_t *conn = sbr_get_conn(sk);
+
+ ret = (addr
+ && addrlen) ? sbr_get_sockaddr_and_len(ss_get_remote_port(conn),
+ ss_get_remote_ip(conn),
+ addr, addrlen) : 0;
+ if (0 != ret)
+ {
+ sbr_set_sk_io_errno(sk, EINVAL);
+ NSSBR_LOGERR("sbr_tcp_get_sockaddr]fd=%d", sk->fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+sbr_tcp_accept_socket(sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen)
+{
+ int err;
+ spl_netconn_t *newconn = NULL;
+
+ err = sbr_tcp_wait_new_conn(sk, (void **) &newconn);
+ if (ERR_OK != err)
+ {
+ return err;
+ }
+
+ err = sbr_init_conn_for_accept(new_sk, newconn);
+ if (ERR_OK != err)
+ {
+ /*When conn is null, return err; then do not need to free conn */
+ return err;
+ }
+
+ err = sbr_tcp_get_sockaddr(new_sk, addr, addrlen);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR("sbr_get_sockaddr_and_socklen]ret=%d.", err);
+ sbr_tcp_accept_failed(new_sk);
+ return -1;
+ }
+
+ NSSBR_LOGINF
+ ("return]listen fd=%d,listen conn=%p,listen private_data=%p,accept fd=%d,accept conn=%p,accept private_data=%p",
+ sk->fd, sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk)),
+ new_sk->fd, sbr_get_conn(new_sk),
+ ss_get_private_data(sbr_get_conn(new_sk)));
+
+ //ip_addr_info_print(SOCKETS_DEBUG, &sbr_get_conn(new_sk)->share_remote_ip);
+
+ /* test_epollCtl_003_001: Accept a conn. Add epoll_ctl with IN event and
+ send a msg from peer. The event will be given once epoll_wait is called.
+ Now, modify to IN|OUT. Calling epoll_event should return immediately since
+ the socket is writable. Currently, returns 0 events.
+ This issue is fixed here
+ */
+
+ /* Prevent automatic window updates, we do this on our own! */
+ ss_set_noautorecved_flag(sbr_get_conn(new_sk), 1);
+
+ ss_set_send_event(sbr_get_conn(new_sk), 1);
+
+ /* don't set conn->last_err: it's only ERR_OK, anyway */
+ return ERR_OK;
+}
+
+NSTACK_STATIC int
+sbr_tcp_accept(sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen)
+{
+ int err;
+
+ /* If conn is not in listen state then return failure with error code: EINVAL(22) */
+ if (!ss_is_listen_state(sbr_get_conn(sk)))
+ {
+ NSSBR_LOGERR("fd is not listening for connections]fd=%d,err=%d",
+ sk->fd, EINVAL);
+ sbr_set_sk_errno(sk, EINVAL);
+
+ return -1;
+ }
+
+ if (ss_is_nonblock_flag(sbr_get_conn(sk))
+ && (0 >= ss_get_recv_event(sbr_get_conn(sk))))
+ {
+ NSSBR_LOGERR("fd is nonblocking and rcvevent<=0]fd=%d,err=%d", sk->fd,
+ EWOULDBLOCK);
+ sbr_set_sk_errno(sk, EWOULDBLOCK);
+
+ return -1;
+ }
+
+ err = ss_get_last_errno(sbr_get_conn(sk));
+ if (SPL_ERR_IS_FATAL(err))
+ {
+ /* don't recv on fatal errors: this might block the application task
+ waiting on acceptmbox forever! */
+ sbr_set_sk_errno(sk, sbr_spl_err_to_errno(err));
+
+ return -1;
+ }
+
+ /* wait for a new connection */
+ err = sbr_tcp_accept_socket(sk, new_sk, addr, addrlen);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR("sbr_tcp_accept_socket failed]fd=%d,err=%d", sk->fd,
+ err);
+
+ return -1;
+ }
+
+ /* Prevent automatic window updates, we do this on our own! */
+ ss_sub_recv_event(sbr_get_conn(sk));
+
+ sbr_set_sk_errno(sk, ERR_OK);
+
+ /* test_epollCtl_003_001: Accept a conn. Add epoll_ctl with IN event and
+ send a msg from peer. The event will be given once epoll_wait is called.
+ Now, modify to IN|OUT. Calling epoll_event should return immediately since
+ the socket is writable. Currently, returns 0 events.
+ This issue is fixed here
+ */
+
+ ss_set_send_event(sbr_get_conn(new_sk), 1);
+
+ return new_sk->fd;
+}
+
+NSTACK_STATIC int
+sbr_tcp_accept4(sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen, int flags)
+{
+ int fd = sbr_tcp_accept(sk, new_sk, addr, addrlen);
+
+ if (0 > fd)
+ {
+ return fd;
+ }
+
+ if (flags & O_NONBLOCK)
+ {
+ int opts = new_sk->fdopt->fcntl(new_sk, F_GETFL, 0);
+ if (opts < 0)
+ {
+ NSSBR_LOGERR("sbr_tcp_fcntl(sock,GETFL)");
+ sbr_tcp_accept_failed(new_sk);
+ return -1;
+ }
+
+ opts = opts | O_NONBLOCK;
+
+ if (new_sk->fdopt->fcntl(new_sk, F_SETFL, opts) < 0)
+
+ {
+ NSSBR_LOGERR("sbr_tcp_fcntl(sock,F_SETFL,opts)");
+ sbr_tcp_accept_failed(new_sk);
+ return -1;
+ }
+ }
+
+ return new_sk->fd;
+}
+
+NSTACK_STATIC int
+sbr_tcp_connect(sbr_socket_t * sk, const struct sockaddr *name,
+ socklen_t namelen)
+{
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name;
+
+ NSSBR_LOGINF("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa(addr_in->sin_addr), ntohs(addr_in->sin_port),
+ sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk)));
+ spl_ip_addr_t remote_addr;
+
+ inet_addr_to_ipaddr(&remote_addr, &addr_in->sin_addr);
+ u16 remote_port = addr_in->sin_port;
+
+ spl_ip_addr_t local_addr = { IPADDR_ANY };
+
+ if (sbr_handle_connect(sk, &remote_addr, ntohs(remote_port), &local_addr)
+ != 0)
+ {
+ NSSBR_LOGERR("fail]fd=%d", sk->fd);
+ return -1;
+ }
+
+ if (ss_is_shut_rd(sbr_get_conn(sk)))
+ {
+ NSSBR_LOGERR("shut_rd]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ECONNRESET);
+ return -1;
+ }
+
+ NSSBR_LOGINF("succeeded]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ERR_OK);
+
+ return 0;
+}
+
+static u8 netconn_shutdown_opt[] = {
+ SPL_NETCONN_SHUT_RD,
+ SPL_NETCONN_SHUT_WR,
+ SPL_NETCONN_SHUT_RDWR
+};
+
+NSTACK_STATIC int sbr_tcp_shutdown(sbr_socket_t * sk, int how)
+{
+ err_t err;
+
+ if (ss_is_listen_state(sbr_get_conn(sk)))
+ {
+ return 0;
+ }
+
+ ss_set_shut_status(sbr_get_conn(sk), how);
+
+ err = sbr_handle_shutdown(sk, netconn_shutdown_opt[how]);
+
+ return (err == ERR_OK ? 0 : -1);
+}
+
+NSTACK_STATIC int
+sbr_tcp_getsockname(sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen)
+{
+
+ NSSBR_LOGINF("sockname]fd=%d,tcp_state=%d", sk->fd,
+ ss_get_tcp_state(sbr_get_conn(sk)));
+
+ return sbr_handle_get_name(sk, name, namelen, SBR_GET_SOCK_NAME);
+}
+
+NSTACK_STATIC int
+sbr_tcp_getpeername(sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen)
+{
+
+ if (SPL_CLOSED == ss_get_tcp_state(sbr_get_conn(sk)))
+ {
+ NSSBR_LOGERR("connection not exist]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, ENOTCONN);
+ return -1;
+ }
+
+ NSSBR_LOGINF("peername]fd=%d,tcp_state=%d", sk->fd,
+ ss_get_tcp_state(sbr_get_conn(sk)));
+
+ return sbr_handle_get_name(sk, name, namelen, SBR_GET_PEER_NAME);
+}
+
+static int
+sbr_getsockopt_ipproto_tcp(int optname, void *optval, socklen_t optlen)
+{
+ int err = ERR_OK;
+
+ switch (optname)
+ {
+ case SPL_TCP_NODELAY:
+ break;
+ case SPL_TCP_KEEPIDLE:
+ case SPL_TCP_KEEPINTVL:
+ case SPL_TCP_KEEPCNT:
+ case SPL_TCP_INFO:
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+NSTACK_STATIC int inline sbr_tcp_set_sockopt_err(sbr_socket_t * sk, int err)
+{
+ if (ENOPROTOOPT == err)
+ {
+ return 0;
+ }
+ else
+ {
+ sbr_set_sk_errno(sk, err);
+ return -1;
+ }
+}
+
+NSTACK_STATIC int inline sbr_tcp_get_sockopt_err(sbr_socket_t * sk, int err)
+{
+ sbr_set_sk_errno(sk, err);
+ return -1;
+}
+
+NSTACK_STATIC int
+sbr_tcp_getsockopt(sbr_socket_t * sk, int level, int optname, void *optval,
+ socklen_t * optlen)
+{
+ int err = 0;
+
+ switch (level)
+ {
+ case SOL_SOCKET:
+ err = sbr_getsockopt_sol_socket(sk, optname, optval, *optlen);
+ break;
+
+ case IPPROTO_IP:
+ err = sbr_getsockopt_ipproto_ip(optname, optval, *optlen);
+ break;
+
+ case IPPROTO_TCP:
+ err = sbr_getsockopt_ipproto_tcp(optname, optval, *optlen);
+ break;
+
+ case NSTACK_SOCKOPT:
+ if ((optname == NSTACK_SEM_SLEEP) || (*optlen < sizeof(u32_t)))
+ {
+ *(u32_t *) optval =
+ sbr_get_fd_share(sk)->block_polling_time / 1000;
+ NSSOC_LOGINF
+ ("tcp get recv sleep time success, usleep time = %d,fd = %d",
+ sbr_get_fd_share(sk)->block_polling_time, sk->fd);
+ return ERR_OK;
+ }
+ else
+ {
+ NSSOC_LOGINF("get recv sleep time failed, fd = %d", sk->fd);
+ sbr_set_sk_io_errno(sk, EINVAL);
+ return -1;
+ }
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ if (0 != err)
+ {
+ NSSBR_LOGERR("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level,
+ optname, err);
+ /* for option not support ,getsockopt() should return fail */
+ return sbr_tcp_get_sockopt_err(sk, err);
+ }
+
+ return sbr_handle_getsockopt(sk, level, optname, optval, optlen);
+}
+
+int sbr_setsockopt_ipproto_tcp(int optname, socklen_t optlen)
+{
+ int err = 0;
+
+ if (optlen < sizeof(int))
+ {
+ return EINVAL;
+ }
+
+ switch (optname)
+ {
+ case SPL_TCP_KEEPIDLE:
+ case SPL_TCP_KEEPINTVL:
+ case SPL_TCP_KEEPCNT:
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+NSTACK_STATIC int
+sbr_tcp_setsockopt(sbr_socket_t * sk, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ int err = 0;
+
+ switch (level)
+ {
+ case SOL_SOCKET:
+ err =
+ sbr_setsockopt_sol_socket(sk, optname, optval, optlen,
+ SPL_NETCONN_TCP);
+ break;
+ case IPPROTO_IP:
+ err =
+ sbr_setsockopt_ipproto_ip(optname, optval, optlen,
+ SPL_NETCONN_TCP);
+ break;
+ case IPPROTO_TCP:
+ err = sbr_setsockopt_ipproto_tcp(optname, optlen);
+ break;
+ case NSTACK_SOCKOPT:
+ {
+ u32_t sleep_time = *(u32_t *) optval;
+ /*sleep time should less than 1s */
+ if ((optname == NSTACK_SEM_SLEEP) && (optlen >= sizeof(u32_t))
+ && (sleep_time < 1000000))
+ {
+ sbr_get_fd_share(sk)->block_polling_time =
+ sleep_time * 1000;
+ NSSOC_LOGINF
+ ("tcp set recv sleep time success, usleep time = %d,fd = %d",
+ sbr_get_fd_share(sk)->block_polling_time, sk->fd);
+ return ERR_OK;
+ }
+ else
+ {
+ NSSOC_LOGINF("set recv sleep time failed, fd = %d",
+ sk->fd);
+ sbr_set_sk_io_errno(sk, EINVAL);
+ return -1;
+ }
+ }
+
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ if (0 != err)
+ {
+ NSSBR_LOGERR("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level,
+ optname, err);
+
+ return sbr_tcp_set_sockopt_err(sk, err);
+ }
+
+ return sbr_handle_setsockopt(sk, level, optname, optval, optlen);
+}
+
+static inline u16 sbr_tcp_mbuf_count(struct spl_pbuf *p)
+{
+ u16 count = 0;
+ struct spl_pbuf *buf = p;
+ struct common_mem_mbuf *mbuf;
+
+ while (buf)
+ {
+ mbuf =
+ (struct common_mem_mbuf *) ((char *) buf -
+ sizeof(struct common_mem_mbuf));
+ while (mbuf)
+ {
+ count++;
+#ifdef HAL_LIB
+#else
+ mbuf = mbuf->next;
+#endif
+ }
+
+ buf = (struct spl_pbuf *) ADDR_SHTOL(buf->next_a);
+ }
+
+ return count;
+}
+
+static inline void sbr_tcp_free_recvbuf(sbr_socket_t * sk, struct spl_pbuf *p)
+{
+ int len;
+
+ if (ss_is_noautorecved_flag(sbr_get_conn(sk)))
+ {
+ len = sbr_tcp_mbuf_count(p);
+ sbr_handle_tcp_recv(sk, len, p);
+ }
+}
+
+static inline void
+sbr_tcp_recv_no_peak(sbr_socket_t * sk, struct spl_pbuf *buf, u32 buflen,
+ u32 copylen)
+{
+ if ((buflen - copylen) > 0)
+ {
+ sbr_get_fd_share(sk)->lastdata = (void *) ADDR_LTOSH(buf);
+ sbr_get_fd_share(sk)->lastoffset += copylen;
+ }
+ else
+ {
+ sbr_get_fd_share(sk)->lastdata = 0;
+ sbr_get_fd_share(sk)->lastoffset = 0;
+ sbr_tcp_free_recvbuf(sk, buf);
+ }
+}
+
+static inline int
+sbr_tcp_recv_from_ring(sbr_socket_t * sk, struct spl_pbuf **buf, i32 timeout)
+{
+ int err;
+ spl_netconn_t *conn = sbr_get_conn(sk);
+
+ err = ss_get_last_errno(conn);
+ if (SPL_ERR_IS_FATAL(err))
+ {
+ /* don't recv on fatal errors: this might block the application task
+ waiting on recvmbox forever! */
+
+ /* @todo: this does not allow us to fetch data that has been put into recvmbox
+ before the fatal error occurred - is that a problem? */
+ NSSBR_LOGDBG("last err when recv:]=%d", err);
+ if (ERR_CLSD != err)
+ {
+ sbr_set_sk_io_errno(sk, sbr_spl_err_to_errno(err));
+ return -1;
+ }
+ }
+
+ *buf = NULL;
+ if (0 != sbr_dequeue_buf(sk, (void **) buf, timeout))
+ {
+ return -1;
+ }
+
+ ss_sub_recv_avail(sbr_get_conn(sk), (*buf)->tot_len);
+
+ ss_sub_recv_event(sbr_get_conn(sk));
+
+ return 0;
+}
+
+static inline int sbr_tcp_recv_state_check(sbr_socket_t * sk)
+{
+
+ spl_tcp_state_t state = ss_get_tcp_state(sbr_get_conn(sk));
+
+ NSSBR_LOGDBG("tcp state when recv:]=%d", state);
+
+ //close_wait state also can recive data
+ //no connect cannot recive data
+ if (SPL_ESTABLISHED > state)
+ {
+ if (SPL_SHUT_WR != ss_get_shut_status(sbr_get_conn(sk)))
+ {
+ /* after all data retrnasmission, connection is active */
+ /* patch solution as last_err is not maintained properly */
+ if ((SPL_CLOSED == state)
+ && (ERR_TIMEOUT == ss_get_last_errno(sbr_get_conn(sk))))
+ {
+ sbr_set_sk_io_errno(sk, ETIMEDOUT);
+ }
+ else if ((SPL_CLOSED == state)
+ && (ERR_RST == ss_get_last_errno(sbr_get_conn(sk))))
+ {
+ sbr_set_sk_io_errno(sk, ECONNRESET);
+ }
+ else
+ {
+ sbr_set_sk_io_errno(sk, ENOTCONN);
+ }
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+NSTACK_STATIC int
+sbr_tcp_recvfrom(sbr_socket_t * sk, void *mem, size_t len, int flags,
+ struct sockaddr *from, socklen_t * fromlen)
+{
+ struct spl_pbuf *p;
+ u32 buflen;
+ u32 copylen;
+ u32 off = 0;
+ u8 done = 0;
+ int para_len = len;
+ int retval = 0;
+
+ sbr_com_lock_recv(sk);
+ NSSOC_LOGINF("recv start, fd = %d last data %p flags to be set %d",
+ sk->fd, ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata),
+ MSG_DONTWAIT);
+
+ if (0 != sbr_tcp_recv_state_check(sk))
+ {
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ do
+ {
+ if (sbr_get_fd_share(sk)->lastdata)
+ {
+ p = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata);
+ }
+ else
+ {
+ if ((flags & MSG_DONTWAIT)
+ || ss_is_nonblock_flag(sbr_get_conn(sk)))
+ {
+ NSSOC_LOGINF("call ss_get_recv_event");
+ if (0 >= ss_get_recv_event(sbr_get_conn(sk)))
+ {
+ NSSOC_LOGINF("no recv event]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EWOULDBLOCK);
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+ }
+
+ if (0 !=
+ sbr_tcp_recv_from_ring(sk, &p,
+ sbr_get_fd_share(sk)->recv_timeout))
+ {
+ /* already received data, return that */
+ if (off > 0)
+ {
+ sbr_set_sk_io_errno(sk, ERR_OK);
+ retval = off;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ /* we tell the user the connection is closed by returning zero */
+ if (sbr_get_sk_errno(sk) == ENOTCONN)
+ {
+ retval = 0;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ sbr_get_fd_share(sk)->lastdata = (void *) ADDR_LTOSH(p);
+ }
+
+ buflen = p->tot_len - sbr_get_fd_share(sk)->lastoffset;
+ copylen = len > buflen ? buflen : len;
+
+ if ((copylen > 0)
+ && 0 == spl_pbuf_copy_partial(p, (u8 *) mem + off, copylen,
+ sbr_get_fd_share(sk)->lastoffset))
+ {
+ NSSBR_LOGERR("copy failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EFAULT);
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ off += copylen;
+
+ len -= copylen;
+
+ if ((len == 0) || (ss_get_recv_event(sbr_get_conn(sk)) <= 0)
+ || ((flags & MSG_PEEK) != 0))
+ {
+ if ((off >= sbr_get_fd_share(sk)->rcvlowat)
+ || (para_len <= sbr_get_fd_share(sk)->rcvlowat))
+ {
+ done = 1;
+ }
+ }
+
+ if (done)
+ {
+ if (sbr_tcp_get_sockaddr(sk, from, fromlen) != 0)
+ {
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+ }
+
+ /* If this is a TCP socket, check if there is data left in the buffer,
+ If so, it should be saved in the sock structure for next time around. */
+ if (!(flags & MSG_PEEK))
+ {
+ sbr_tcp_recv_no_peak(sk, p, buflen, copylen);
+ }
+ }
+ while (!done);
+
+ retval = off;
+
+ NSSOC_LOGINF("recv done, fd = %d last data %p", sk->fd);
+ sbr_tcp_recvfrom_exit:
+
+ NSSOC_LOGINF("recv exit, fd = %d last data %p", sk->fd);
+ sbr_com_unlock_recv(sk);
+ return retval;
+}
+
+/*****************************************************************************
+* Prototype : sbr_tcp_recvdata
+* Description : recvdata
+* Input : sbr_socket_t* sk
+* const struct iovec* iov
+* int iovcnt
+* int flags
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_tcp_recvdata(sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ int max = SBR_MAX_INTEGER;
+ int len = 0;
+ int ret = 0;
+ int i = 0;
+
+ do
+ {
+ len += ret;
+
+ if (!iov[i].iov_base || (0 == iov[i].iov_len))
+ {
+ ret = 0;
+ continue;
+ }
+
+ ret =
+ sbr_tcp_recvfrom(sk, (char *) iov[i].iov_base, iov[i].iov_len, 0,
+ NULL, NULL);
+ }
+ while ((ret == (int) iov[i].iov_len) && (iovcnt > (++i))
+ && (max - len - ret > (int) iov[i].iov_len));
+
+ if (len == 0)
+ {
+ return ret;
+ }
+ else
+ {
+ return (ret == -1 ? len : len + ret);
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_tcp_readv
+* Description : readv
+* Input : sbr_socket_t* sk
+* const struct iovec* iov
+* int iovcnt
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_tcp_readv(sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ return sbr_tcp_recvdata(sk, iov, iovcnt);
+}
+
+/*****************************************************************************
+* Prototype : sbr_tcp_recvmsg
+* Description : recvmsg,unsupport flags
+* Input : sbr_socket_t* sk
+* struct msghdr* msg
+* int flags
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int sbr_tcp_recvmsg(sbr_socket_t * sk, struct msghdr *msg, int flags)
+{
+ if (sbr_tcp_get_sockaddr
+ (sk, (struct sockaddr *) msg->msg_name, &msg->msg_namelen) != 0)
+ {
+ return -1;
+ }
+
+ return sbr_tcp_recvdata(sk, msg->msg_iov, msg->msg_iovlen);
+}
+
+static int
+sbr_tcp_send_is_timeout(sbr_socket_t * sk, struct timespec *starttm)
+{
+ struct timespec currtm;
+ i64 timediff_ms, timediff_sec;
+ i64 timeout_thr_ms, timeout_thr_sec;
+
+ timeout_thr_ms = sbr_get_fd_share(sk)->send_timeout;
+ if (0 == timeout_thr_ms)
+ {
+ return 0;
+ }
+
+ /* it is possible that starttm don't be inited,
+ if send_timeout is change when this write function is running */
+ timeout_thr_sec = (timeout_thr_ms + 240) >> 10;
+
+ /* Handle system time change side-effects */
+ if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &currtm)))
+ {
+ NSSBR_LOGERR("Failed to get time, errno = %d", errno);
+ }
+
+ timediff_sec = currtm.tv_sec - starttm->tv_sec;
+ if (timediff_sec >= timeout_thr_sec)
+ {
+ timediff_ms = currtm.tv_nsec > starttm->tv_nsec ?
+ (timediff_sec * 1000) + (currtm.tv_nsec -
+ starttm->tv_nsec) /
+ USEC_TO_SEC : (timediff_sec * 1000) -
+ ((starttm->tv_nsec - currtm.tv_nsec) / USEC_TO_SEC);
+
+ /*NOTE: if user configured the timeout as say 0.5 ms, then timediff value
+ will be negetive if still 0.5 ms is not elapsed. this is intended and we should
+ not typecast to any unsigned type during this below if check */
+ if (timediff_ms > timeout_thr_ms)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static inline int
+sbr_tcp_write_is_wait(sbr_socket_t * sk, struct timespec *starttm,
+ int noneblockFlg)
+{
+ if (noneblockFlg || sbr_tcp_send_is_timeout(sk, starttm))
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+static struct spl_pbuf *sbr_tcp_write_alloc_buf(sbr_socket_t * sk,
+ size_t seglen, u8 api_flag,
+ struct timespec *starttm,
+ u8 * errno_flag)
+{
+ spl_netconn_t *conn = sbr_get_conn(sk);
+
+ struct spl_pbuf *curr_buf = NULL;
+ size_t head_len = SPL_TCP_HLEN + SPL_PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN;
+ int noneblockFlg = (api_flag & SPL_NETCONN_DONTBLOCK)
+ || ss_is_nonblock_flag(sbr_get_conn(sk));
+
+ do
+ {
+ /* When packages are lost more than TCP_MAXRTX times,
+ * conn will be closed and pcb will be removed. */
+ if (ss_get_tcp_state(conn) == SPL_CLOSED)
+ {
+ NSSBR_LOGERR("pcb SPL_CLOSED]conn=%p", conn);
+ sbr_set_sk_io_errno(sk, ECONNABORTED);
+ /* Must set errno_flag when set errno, to avoid errnno overwritten by sbr_tcp_write */
+ *errno_flag = 1;
+ return NULL;
+ }
+
+ curr_buf = sbr_malloc_tx_pbuf(seglen + head_len, head_len);
+ if (NULL == curr_buf)
+ {
+ if (!sbr_tcp_write_is_wait(sk, starttm, noneblockFlg))
+ {
+ return NULL;
+ }
+
+ int err = ss_get_last_errno(sbr_get_conn(sk));
+ if (SPL_ERR_IS_FATAL(err))
+ {
+ NSSBR_LOGERR("connection fatal error!err=%d", err);
+ sbr_set_sk_io_errno(sk, sbr_spl_err_to_errno(err));
+ *errno_flag = 1;
+ return NULL;
+ }
+
+ sched_yield();
+ }
+ }
+ while (curr_buf == NULL);
+
+ return curr_buf;
+}
+
+static inline void
+sbr_tcp_write_rel_buf(sbr_socket_t * sk, struct spl_pbuf *buf,
+ u32 thread_index)
+{
+ if (buf != NULL)
+ {
+ sbr_handle_free_send_buf(sk, buf);
+ }
+}
+
+static inline int
+sbr_tcp_write_fill_buf(const void *data, size_t * pos,
+ struct spl_pbuf *seg_buf, size_t seglen, size_t optlen)
+{
+ size_t start = *pos;
+ size_t copy = seglen;
+ struct spl_pbuf *first = seg_buf;
+
+ while ((0 < copy) && (NULL != first))
+ {
+ char *dst_ptr = PTR_SHTOL(char *, first->payload_a) + optlen;
+
+ if (NULL ==
+ common_memcpy(dst_ptr, (u8_t *) data + start,
+ first->len - optlen))
+ {
+ NSSBR_LOGERR("common_memcpy error]dst=%p,src=%p,len=%u",
+ dst_ptr, (u8_t *) data + start, first->len);
+ return -1;
+ }
+
+ start += (first->len - optlen);
+ copy -= (first->len - optlen);
+ first = ADDR_SHTOL(first->next_a);
+ }
+
+ (*pos) = start;
+
+ return 0;
+}
+
+static inline int
+sbr_tcp_writev_fill_buf(const struct iovec *iov, size_t * iov_pos,
+ int *iov_var, size_t * pos, struct spl_pbuf *seg_buf,
+ size_t seglen, size_t optlen)
+{
+ size_t valid_copy_len;
+ size_t iov_data_left;
+
+ size_t copy = seglen;
+ size_t start = *pos;
+ size_t current_iov_pos = *iov_pos;
+ int current_iov_var = *iov_var;
+
+ u32 pbuf_offset = optlen;
+ u32 pbuf_data_len;
+ struct spl_pbuf *first = seg_buf;
+
+ while ((0 < copy) && (NULL != first))
+ {
+ iov_data_left = iov[current_iov_var].iov_len - current_iov_pos;
+ if (seglen == copy)
+ {
+ pbuf_offset = optlen;
+ }
+
+ pbuf_data_len = first->len - pbuf_offset;
+ valid_copy_len =
+ (iov_data_left > pbuf_data_len ? pbuf_data_len : iov_data_left);
+ if (NULL ==
+ common_memcpy((char *) ADDR_SHTOL(first->payload_a) + pbuf_offset,
+ (u8_t *) iov[current_iov_var].iov_base +
+ current_iov_pos, valid_copy_len))
+ {
+ NSSBR_LOGERR
+ ("common_memcpy error]current_iov_var=%d, dst=%p,src=%p,len=%zu",
+ current_iov_var,
+ (char *) ADDR_SHTOL(first->payload_a) + pbuf_offset,
+ (u8_t *) iov[current_iov_var].iov_base + current_iov_pos,
+ valid_copy_len);
+ return -1;
+ }
+
+ start += valid_copy_len;
+ copy -= valid_copy_len;
+
+ if (iov_data_left == pbuf_data_len)
+ {
+ first = PTR_SHTOL(struct spl_pbuf *, first->next_a);
+ pbuf_offset = optlen; //+= valid_copy_len;
+ current_iov_var++;
+ current_iov_pos = 0;
+ }
+ else if (iov_data_left > pbuf_data_len)
+ {
+ first = PTR_SHTOL(struct spl_pbuf *, first->next_a);
+ pbuf_offset = optlen; //+= valid_copy_len;
+ current_iov_pos += valid_copy_len;
+ }
+ else
+ {
+ pbuf_offset += valid_copy_len;
+
+ current_iov_var++;
+ current_iov_pos = 0;
+ }
+ }
+
+ *iov_pos = current_iov_pos;
+ *iov_var = current_iov_var;
+ *pos = start;
+
+ return 0;
+}
+
+static inline void
+sbr_tcp_write_add_buf_to_list(struct spl_pbuf **p_head,
+ struct spl_pbuf **p_tail,
+ struct spl_pbuf *seg_buf, size_t seglen,
+ size_t optlen)
+{
+ seg_buf->len = seglen + optlen;
+ seg_buf->tot_len = seglen + optlen;
+ seg_buf->next_a = 0;
+
+ /*put seg_buf after p_head */
+ if (NULL == (*p_head))
+ {
+ (*p_head) = seg_buf;
+ (*p_tail) = seg_buf;
+ }
+ else
+ {
+ (*p_tail)->next_a = ADDR_LTOSH(seg_buf);
+ (*p_tail) = seg_buf;
+ }
+}
+
+NSTACK_STATIC int
+sbr_tcp_write(sbr_socket_t * sk, const void *data, size_t size, u8 api_flag,
+ size_t * written)
+{
+ err_t err = -1;
+ size_t pos = 0, left, seglen;
+ u32 pbuf_seg_cnt = 0;
+ u32 thread_index = 0;
+ struct spl_pbuf *seg_buf = NULL;
+ struct spl_pbuf *p_head = NULL;
+ struct spl_pbuf *p_tail = p_head;
+ struct spl_netconn *conn = sbr_get_conn(sk);
+ u32 mss = ss_get_mss(sbr_get_conn(sk));
+
+ if (0 == size)
+ {
+ NSSBR_LOGERR("fd=%d,size=%u", sk->fd, (u32) size);
+ return 0;
+ }
+
+ struct timespec ts;
+ if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &ts)))
+ {
+ NSSBR_LOGERR("Failed to get time, errno = %d", errno);
+ }
+
+ while (pos < size)
+ {
+ left = size - pos;
+ seglen = left > mss ? mss : left;
+ u8 errno_set = 0;
+ seg_buf =
+ sbr_tcp_write_alloc_buf(sk, seglen, api_flag, &ts, &errno_set);
+ if (NULL == seg_buf)
+ {
+ NSSBR_LOGINF("sbr_tcp_write_alloc_buf failed......");
+ if (NULL != p_head)
+ {
+ err = sbr_handle_tcp_send(sk, size, p_head, api_flag);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR("sbr_handle_tcp_send error]err(%d)", err);
+ goto err_ref_buf;
+ }
+ }
+
+ if (0 == pos)
+ {
+ /* If errno is already set in sbr_tcp_write_alloc_buf, do not overwrite here */
+ if (!errno_set)
+ {
+ sbr_set_sk_io_errno(sk, EWOULDBLOCK);
+ }
+ return -1;
+ }
+
+ NSSBR_LOGDBG("sent size %zu", pos);
+ *written = pos;
+
+ return ERR_OK;
+ }
+
+ if (0 != sbr_tcp_write_fill_buf(data, &pos, seg_buf, seglen, 0))
+ {
+ sbr_set_sk_io_errno(sk, EFAULT);
+ NSSBR_LOGERR("sbr_tcp_write_fill_buf error]");
+ goto err_ref_buf;
+ }
+
+ sbr_tcp_write_add_buf_to_list(&p_head, &p_tail, seg_buf, seglen, 0);
+
+ ++pbuf_seg_cnt;
+ if (p_head
+ && ((SPL_TCP_SEND_MAX_SEG_PER_MSG <= pbuf_seg_cnt)
+ || (pos >= size)))
+ {
+ pbuf_seg_cnt = 0;
+ err = sbr_handle_tcp_send(sk, size, p_head, api_flag);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR("sbr_handle_tcp_send error]err(%d)", err);
+ goto err_ref_buf;
+ }
+
+ p_head = NULL;
+ }
+ }
+
+ *written = size;
+
+ (void) conn;
+ return ERR_OK;
+
+ err_ref_buf:
+ sbr_tcp_write_rel_buf(sk, p_head, thread_index);
+ (void) conn;
+ return -1;
+}
+
+NSTACK_STATIC int
+sbr_tcp_writev(sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ err_t err = -1;
+ int idx = 0;
+ size_t pos = 0, left, seglen, optlen = 0;
+ u32 pbuf_seg_cnt = 0;
+ u32 thread_index = 0;
+ size_t size = 0;
+ size_t iov_pos = 0;
+ int iov_var = 0;
+ struct spl_pbuf *seg_buf = NULL;
+ struct spl_pbuf *p_head = NULL;
+ struct spl_pbuf *p_tail = p_head;
+ struct spl_netconn *conn = sbr_get_conn(sk);
+ u32 mss = ss_get_mss(sbr_get_conn(sk));
+
+ if (mss <= optlen)
+ {
+ NSSBR_LOGERR("mss invalid]mss=%u,optlen=%zu,fd=%d", mss, optlen,
+ sk->fd);
+ sbr_set_sk_io_errno(sk, EINVAL);
+ return -1;
+ }
+
+ /* mss dose't include the tcp options length */
+ mss -= optlen;
+
+ while (idx < iovcnt)
+ {
+ if (SBR_MAX_INTEGER - iov[idx].iov_len <= size)
+ {
+ size = SBR_MAX_INTEGER;
+ break;
+ }
+
+ size += iov[idx].iov_len;
+ idx++;
+ }
+
+ struct timespec starttm;
+ if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &starttm)))
+ {
+ NSSBR_LOGERR("Failed to get time, errno = %d", errno);
+ }
+
+ while (pos < size)
+ {
+ left = size - pos;
+
+ seglen = left > mss ? mss : left;
+ u8 errno_set = 0;
+ seg_buf =
+ sbr_tcp_write_alloc_buf(sk, seglen + optlen, SPL_NETCONN_COPY,
+ &starttm, &errno_set);
+ if (NULL == seg_buf)
+ {
+ if (NULL != p_head)
+ {
+ err = sbr_handle_tcp_send(sk, size, p_head, SPL_NETCONN_COPY);
+ /*If errno is already set in sbr_tcp_write_alloc_buf, do not overwrite here */
+ if (err != ERR_OK)
+ {
+ NSSBR_LOGERR("sbr_handle_tcp_send error]err(%d)", err);
+ goto err_ref_buf;
+ }
+ }
+
+ /* [Start]
+ 1)Set SO_SNDTIMEO to 10
+ 2)Send a msg of larger buff size.and let the timeout happen for send (dont receive at peer side.)
+ 3)iRet will be 0 and errno received will be 11 (EAGAIN).
+
+ Above issue is fixed.
+ */
+ if (0 == pos)
+ {
+ if (!errno_set)
+ {
+ sbr_set_sk_io_errno(sk, EWOULDBLOCK);
+ }
+ return -1;
+ }
+ /* [End] */
+
+ NSSBR_LOGDBG("sent size %zu", pos);
+
+ return pos;
+ }
+
+ if (0 !=
+ sbr_tcp_writev_fill_buf(iov, &iov_pos, &iov_var, &pos, seg_buf,
+ seglen, optlen))
+ {
+ sbr_set_sk_io_errno(sk, EFAULT);
+ NSSBR_LOGERR("sbr_tcp_writev_fill_buf error]");
+ goto err_ref_buf;
+ }
+
+ sbr_tcp_write_add_buf_to_list(&p_head, &p_tail, seg_buf, seglen,
+ optlen);
+
+ /* @todo: for non-blocking write, check if 'size' would ever fit into
+ snd_queue or snd_buf */
+ ++pbuf_seg_cnt;
+ if (p_head
+ && ((SPL_TCP_SEND_MAX_SEG_PER_MSG <= pbuf_seg_cnt)
+ || (pos >= size)))
+ {
+ pbuf_seg_cnt = 0;
+ err = sbr_handle_tcp_send(sk, size, p_head, SPL_NETCONN_COPY);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR("sbr_handle_tcp_send error]err(%d)", err);
+ goto err_ref_buf;
+ }
+
+ p_head = NULL;
+ }
+ }
+ (void) conn;
+ return size;
+
+ err_ref_buf:
+ sbr_tcp_write_rel_buf(sk, p_head, thread_index);
+ (void) conn;
+ return -1;
+}
+
+NSTACK_STATIC int
+sbr_tcp_sendto(sbr_socket_t * sk, const void *data, size_t size, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ return sk->fdopt->send(sk, data, size, flags);
+}
+
+static inline int sbr_tcp_send_state_check(sbr_socket_t * sk)
+{
+ if ((SPL_SHUT_WR == ss_get_shut_status(sbr_get_conn(sk)))
+ || (SPL_SHUT_RDWR == ss_get_shut_status(sbr_get_conn(sk))))
+ {
+ sbr_set_sk_io_errno(sk, EPIPE);
+ return -1;
+ }
+
+ spl_tcp_state_t state = ss_get_tcp_state(sbr_get_conn(sk));
+ if ((SPL_ESTABLISHED != state) && (SPL_CLOSE_WAIT != state))
+ {
+ /* after all data retrnasmission, connection is active */
+ /* patch solution as last_err is not maintained properly */
+ if ((SPL_CLOSED == state)
+ && (ERR_TIMEOUT == ss_get_last_errno(sbr_get_conn(sk))))
+ {
+ sbr_set_sk_io_errno(sk, ETIMEDOUT);
+ }
+ else if ((SPL_CLOSED == state)
+ && (ERR_RST == ss_get_last_errno(sbr_get_conn(sk))))
+ {
+ sbr_set_sk_io_errno(sk, ECONNRESET);
+ }
+ else
+ {
+ sbr_set_sk_io_errno(sk, EPIPE);
+ }
+
+ return -1;
+ }
+
+ return 0;
+}
+
+NSTACK_STATIC int
+sbr_tcp_send(sbr_socket_t * sk, const void *data, size_t size, int flags)
+{
+ int err;
+ size_t written = 0;
+ u8 write_flags;
+
+ if (0 != sbr_tcp_send_state_check(sk))
+ {
+ NSSBR_LOGDBG("tcp state not correct]fd=%d, err=%d", sk->fd,
+ sbr_get_sk_errno(sk));
+ return -1;
+ }
+
+ write_flags = SPL_NETCONN_COPY |
+ ((flags & MSG_MORE) ? SPL_NETCONN_MORE : 0) |
+ ((flags & MSG_DONTWAIT) ? SPL_NETCONN_DONTBLOCK : 0);
+
+ NSSBR_LOGINF("Sbr tcp write start");
+ err = sbr_tcp_write(sk, data, size, write_flags, &written);
+ NSSBR_LOGINF("Sbr tcp write end written %d", written);
+
+ return (err == ERR_OK ? written : -1);
+}
+
+NSTACK_STATIC int
+sbr_tcp_sendmsg(sbr_socket_t * sk, const struct msghdr *pmsg, int flags)
+{
+ if (0 != sbr_tcp_send_state_check(sk))
+ {
+ NSSBR_LOGDBG("tcp state not correct]fd=%d, err=%d", sk->fd,
+ sbr_get_sk_errno(sk));
+ return -1;
+ }
+
+ return sbr_tcp_writev(sk, pmsg->msg_iov, pmsg->msg_iovlen);
+}
+
+NSTACK_STATIC int sbr_tcp_fcntl(sbr_socket_t * sk, int cmd, long arg)
+{
+ int ret = 0;
+
+ switch (cmd)
+ {
+ case F_GETFL:
+ ret = ss_get_nonblock_flag(sbr_get_conn(sk));
+ NSSBR_LOGDBG("F_GETFL]fd=%d,ret=%d", sk->fd, ret);
+ break;
+
+ case F_SETFL:
+ if (arg & O_NONBLOCK)
+ {
+ NSSBR_LOGDBG("F_SETFL set O_NONBLOCK val]fd=%d,arg=%ld",
+ sk->fd, arg);
+ ss_set_nonblock_flag(sbr_get_conn(sk), (arg & O_NONBLOCK));
+ }
+ else
+ {
+ NSSBR_LOGDBG("F_SETFL clean O_NONBLOCK val]fd=%d,arg=%ld",
+ sk->fd, arg);
+ ss_set_nonblock_flag(sbr_get_conn(sk), 0);
+ }
+
+ break;
+
+ default:
+ NSSBR_LOGERR("cmd is not support]fd=%d,cmd=%d", sk->fd, cmd);
+ ret = -1;
+ sbr_set_sk_errno(sk, EINVAL);
+ break;
+ }
+
+ return ret;
+}
+
+NSTACK_STATIC int
+sbr_tcp_ioctl(sbr_socket_t * sk, unsigned long cmd, void *arg)
+{
+ int ret = 0;
+ int recv_avail;
+
+ switch (cmd)
+ {
+ case FIONREAD:
+ {
+ if (ss_is_listen_state(sbr_get_conn(sk)))
+ {
+ ret = -1;
+ sbr_set_sk_errno(sk, EINVAL);
+ break;
+ }
+
+ recv_avail = ss_get_recv_avail(sbr_get_conn(sk));
+ *((u32 *) arg) = recv_avail >= 0 ? recv_avail : 0;
+ if (sbr_get_fd_share(sk)->lastdata)
+ {
+ struct spl_pbuf *buf =
+ ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata);
+ *((u32 *) arg) +=
+ (buf->tot_len - sbr_get_fd_share(sk)->lastoffset);
+ }
+ }
+
+ break;
+
+ case FIONBIO:
+ {
+ u8 val = 0;
+
+ if (arg && *(u32 *) arg)
+ {
+ val = 1;
+ }
+
+ ss_set_nonblock_flag(sbr_get_conn(sk), val);
+ NSSBR_LOGDBG("FIONBIO]fd=%d,val=%u", sk->fd, val);
+ }
+
+ break;
+
+ default:
+ {
+ NSSBR_LOGERR("cmd is not support]fd=%d,cmd=%lu", sk->fd, cmd);
+ ret = -1;
+ sbr_set_sk_errno(sk, ENOTTY);
+ }
+ break;
+ }
+
+ return ret;
+}
+
+NSTACK_STATIC int sbr_tcp_close(sbr_socket_t * sk)
+{
+ if (sbr_get_fd_share(sk)->lastdata)
+ {
+ struct spl_netbuf *buf = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata);
+ struct spl_pbuf *p = (struct spl_pbuf *) ADDR_SHTOL(buf->p);
+ sbr_tcp_free_recvbuf(sk, p);
+ }
+
+ return sbr_handle_close(sk, 0);
+}
+
+sbr_fdopt tcp_fdopt = {
+ .socket = sbr_tcp_socket,
+ .bind = sbr_tcp_bind,
+ .listen = sbr_tcp_listen,
+ .accept = sbr_tcp_accept,
+ .accept4 = sbr_tcp_accept4,
+ .connect = sbr_tcp_connect,
+ .shutdown = sbr_tcp_shutdown,
+ .getsockname = sbr_tcp_getsockname,
+ .getpeername = sbr_tcp_getpeername,
+ .getsockopt = sbr_tcp_getsockopt,
+ .setsockopt = sbr_tcp_setsockopt,
+ .recvfrom = sbr_tcp_recvfrom,
+ .readv = sbr_tcp_readv,
+ .recvmsg = sbr_tcp_recvmsg,
+ .send = sbr_tcp_send,
+ .sendto = sbr_tcp_sendto,
+ .sendmsg = sbr_tcp_sendmsg,
+ .writev = sbr_tcp_writev,
+ .fcntl = sbr_tcp_fcntl,
+ .ioctl = sbr_tcp_ioctl,
+ .close = sbr_tcp_close,
+ .peak = sbr_com_peak,
+ .lock_common = sbr_com_lock_common,
+ .unlock_common = sbr_com_unlock_common,
+ .fork_parent = sbr_com_fork_parent,
+ .fork_child = sbr_com_fork_child,
+ .ep_getevt = stackx_eventpoll_getEvt,
+ .ep_triggle = stackx_eventpoll_triggle,
+ .set_close_stat = NULL,
+};
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_udp.c b/stacks/lwip_stack/lwip_src/socket/stackx_udp.c
new file mode 100644
index 0000000..937c444
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_udp.c
@@ -0,0 +1,1149 @@
+/*
+*
+* 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 "stackx_prot_com.h"
+#include "stackx_msg_handler.h"
+#include "stackx_pbuf.h"
+#include "stackx_epoll_api.h"
+#include "stackx_err.h"
+#include "nstack_securec.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_cfg.h"
+#include <netinet/in.h>
+#ifdef HAL_LIB
+#else
+#include "rte_memcpy.h"
+#endif
+
+#define SPL_PBUF_UDP_LEN (SPL_FRAME_MTU + SPL_PBUF_LINK_HLEN)
+#define L2_L3_ROOM_LEN (SPL_PBUF_LINK_HLEN + SPL_PBUF_IP_HLEN)
+#define L4_ROOM_LEN SPL_PBUF_UDP_HLEN
+
+/*****************************************************************************
+* Prototype : sbr_udp_socket
+* Description : create socket
+* Input : sbr_socket_t * sk
+* int domain
+* int type
+* int protocol
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_socket(sbr_socket_t * sk, int domain, int type, int protocol)
+{
+ if (sbr_malloc_conn_for_sk(sk, SPL_NETCONN_UDP) != 0)
+ {
+ return -1;
+ }
+
+ int ret = sbr_handle_socket(sk, SPL_NETCONN_UDP, 0);
+ if (ret != 0)
+ {
+ sbr_free_conn_from_sk(sk);
+ return ret;
+ }
+
+ ss_set_nonblock_flag(sbr_get_conn(sk), (type & O_NONBLOCK));
+ ss_set_send_event(sbr_get_conn(sk), 1);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_bind
+* Description : udp bind
+* Input : sbr_socket_t * sk
+* const struct sockaddr * name
+* socklen_t namelen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_bind(sbr_socket_t * sk, const struct sockaddr *name,
+ socklen_t namelen)
+{
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name;
+
+ NSSBR_LOGINF("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa(addr_in->sin_addr), ntohs(addr_in->sin_port),
+ sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk)));
+ spl_ip_addr_t local_addr;
+ inet_addr_to_ipaddr(&local_addr, &addr_in->sin_addr);
+ u16 local_port = addr_in->sin_port;
+ return sbr_handle_bind(sk, &local_addr, ntohs(local_port));
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_listen
+* Description : unsupport
+* Input : sbr_socket_t * sk
+* int backlog
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int sbr_udp_listen(sbr_socket_t * sk, int backlog)
+{
+ NSSBR_LOGERR("type is not TCP]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, EOPNOTSUPP);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_accept
+* Description : unsupport
+* Input : sbr_socket_t * sk
+* sbr_socket_t * new_sk
+* struct sockaddr * addr
+* socklen_t * addrlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_accept(sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen)
+{
+ NSSBR_LOGERR("type is not TCP]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, EOPNOTSUPP);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_accept4
+* Description : unsupport
+* Input : sbr_socket_t * sk
+* sbr_socket_t * new_sk
+* struct sockaddr * addr
+* socklen_t * addrlen
+* int flags
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_accept4(sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen, int flags)
+{
+ NSSBR_LOGERR("type is not TCP]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, EOPNOTSUPP);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_connect
+* Description : udp connect
+* Input : sbr_socket_t * sk
+* const struct sockaddr * name
+* socklen_t namelen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_connect(sbr_socket_t * sk, const struct sockaddr *name,
+ socklen_t namelen)
+{
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name;
+
+ NSSBR_LOGINF("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa(addr_in->sin_addr), ntohs(addr_in->sin_port),
+ sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk)));
+ spl_ip_addr_t remote_addr;
+
+ inet_addr_to_ipaddr(&remote_addr, &addr_in->sin_addr);
+ u16 remote_port = addr_in->sin_port;
+
+ spl_ip_addr_t local_addr = { IPADDR_ANY };
+
+ return sbr_handle_connect(sk, &remote_addr, ntohs(remote_port),
+ &local_addr);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_shutdown
+* Description : udp shutdown
+* Input : sbr_socket_t * sk
+* int how
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int sbr_udp_shutdown(sbr_socket_t * sk, int how)
+{
+ ss_set_shut_status(sbr_get_conn(sk), how);
+ NSSBR_LOGERR("type is not TCP]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, EOPNOTSUPP);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_getsockname
+* Description : get sock name
+* Input : sbr_socket_t * sk
+* struct sockaddr * name
+* socklen_t * namelen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_getsockname(sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen)
+{
+ return sbr_handle_get_name(sk, name, namelen, SBR_GET_SOCK_NAME);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_getpeername
+* Description : get peer name
+* Input : sbr_socket_t * sk
+* struct sockaddr * name
+* socklen_t * namelen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_getpeername(sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen)
+{
+ return sbr_handle_get_name(sk, name, namelen, SBR_GET_PEER_NAME);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_getsockopt
+* Description : get sockopt
+* Input : sbr_socket_t * sk
+* int level
+* int optname
+* void * optval
+* socklen_t * optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_getsockopt(sbr_socket_t * sk, int level, int optname, void *optval,
+ socklen_t * optlen)
+{
+ int err = 0;
+
+ switch (level)
+ {
+ case SOL_SOCKET:
+ err = sbr_getsockopt_sol_socket(sk, optname, optval, *optlen);
+ break;
+ case IPPROTO_IP:
+ err = sbr_getsockopt_ipproto_ip(optname, optval, *optlen);
+ break;
+
+ case NSTACK_SOCKOPT:
+ if ((optname == NSTACK_SEM_SLEEP) || (*optlen < sizeof(u32_t)))
+ {
+ *(u32_t *) optval =
+ sbr_get_fd_share(sk)->block_polling_time / 1000;
+ NSSOC_LOGINF
+ ("udp get recv sleep time success]usleep time=%d,fd=%d",
+ sbr_get_fd_share(sk)->block_polling_time, sk->fd);
+ return ERR_OK;
+ }
+ else
+ {
+ NSSOC_LOGINF("get recv sleep time failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EINVAL);
+ return -1;
+ }
+
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ if (err != 0)
+ {
+ NSSBR_LOGERR("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level,
+ optname, err);
+ /* for option not support ,getsockopt() should return fail */
+ sbr_set_sk_errno(sk, err);
+ return -1;
+ }
+
+ return sbr_handle_getsockopt(sk, level, optname, optval, optlen);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_setsockopt
+* Description : set sockopt
+* Input : sbr_socket_t * sk
+* int level
+* int optname
+* const void * optval
+* socklen_t optlen
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_setsockopt(sbr_socket_t * sk, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ NSSBR_LOGDBG("udp setsockopt]fd=%d,level=%d,optname=%d", sk->fd, level,
+ optname);
+ int err = 0;
+ switch (level)
+ {
+ case SOL_SOCKET:
+ err =
+ sbr_setsockopt_sol_socket(sk, optname, optval, optlen,
+ SPL_NETCONN_UDP);
+ break;
+ case IPPROTO_IP:
+ err =
+ sbr_setsockopt_ipproto_ip(optname, optval, optlen,
+ SPL_NETCONN_UDP);
+ break;
+ case NSTACK_SOCKOPT:
+ {
+ u32_t sleep_time = *(u32_t *) optval;
+ /*sleep time should less than 1s */
+ if ((optname == NSTACK_SEM_SLEEP) && (optlen >= sizeof(u32_t))
+ && (sleep_time < 1000000))
+ {
+ sbr_get_fd_share(sk)->block_polling_time =
+ sleep_time * 1000;
+ NSSOC_LOGINF
+ ("udp set recv sleep time success]usleep time=%d,fd=%d",
+ sbr_get_fd_share(sk)->block_polling_time, sk->fd);
+ return ERR_OK;
+ }
+ else
+ {
+ NSSOC_LOGINF("set recv sleep time failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EINVAL);
+ return -1;
+ }
+ }
+
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ if (err != 0)
+ {
+ NSSBR_LOGERR("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level,
+ optname, err);
+
+ if (ENOPROTOOPT == err)
+ {
+ return 0;
+ }
+ else
+ {
+ sbr_set_sk_errno(sk, err);
+ return -1;
+ }
+ }
+
+ return sbr_handle_setsockopt(sk, level, optname, optval, optlen);
+}
+
+static inline int
+sbr_udp_get_from_addr(sbr_socket_t * sk, struct sockaddr *from,
+ socklen_t * fromlen, struct spl_netbuf *buf)
+{
+ int ret;
+ u16 port = netbuf_fromport(buf);
+ spl_ip_addr_t *addr = netbuf_fromaddr(buf);
+
+ ret = (from
+ && fromlen) ? sbr_get_sockaddr_and_len(port, addr, from,
+ fromlen) : 0;
+ if (0 != ret)
+ {
+ sbr_set_sk_io_errno(sk, EINVAL);
+ NSSBR_LOGERR("sbr_udp_get_from_addr]fd=%d", sk->fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_recv_from_ring
+* Description : recv buf from ring
+* Input : sbr_socket_t * sk
+* struct spl_netbuf ** buf
+* i32 timeout
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_udp_recv_from_ring(sbr_socket_t * sk, struct spl_netbuf **buf,
+ i32 timeout)
+{
+ void *p = NULL;
+ spl_netconn_t *conn = sbr_get_conn(sk);
+
+ if (sbr_dequeue_buf(sk, &p, timeout) != 0)
+ {
+ return -1;
+ }
+
+ *buf = (struct spl_netbuf *) ((char *) p + sizeof(struct spl_pbuf));
+ ss_sub_recv_event(conn);
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : _sbr_udp_recvfrom
+* Description : base recvfrom,without lock
+* Input : sbr_socket_t * sk
+* void * mem
+* size_t len
+* int flags
+* struct sockaddr * from
+* socklen_t * fromlen
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+_sbr_udp_recvfrom(sbr_socket_t * sk, void *mem, size_t len, int flags,
+ struct sockaddr *from, socklen_t * fromlen)
+{
+ struct spl_netbuf *buf = NULL;
+ struct spl_pbuf *p;
+ u32 buflen;
+ u32 copylen;
+ u32 off = 0;
+
+ if (sbr_get_fd_share(sk)->lastdata)
+ {
+ buf = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata);
+ }
+ else
+ {
+ if ((flags & MSG_DONTWAIT) || ss_is_nonblock_flag(sbr_get_conn(sk)))
+ {
+ /*
+ * return with last err when
+ * some fatal err occurs, for example, spl just recovered from a fault.
+ */
+ int err = ss_get_last_errno(sbr_get_conn(sk));
+ if (SPL_ERR_IS_FATAL(err))
+ {
+ NSSBR_LOGDBG("connection fatal error]sk->fd=%d,errno=%d",
+ sk->fd, err);
+ sbr_set_sk_io_errno(sk, sbr_spl_err_to_errno(err));
+ return -1;
+ }
+
+ if (ss_get_recv_event(sbr_get_conn(sk)) <= 0)
+ {
+ NSSBR_LOGDBG("no recv event]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EWOULDBLOCK);
+ return -1;
+ }
+ }
+
+ if (sbr_udp_recv_from_ring
+ (sk, &buf, sbr_get_fd_share(sk)->recv_timeout) != 0)
+ {
+ return -1;
+ }
+
+ sbr_get_fd_share(sk)->lastdata = (void *) ADDR_LTOSH(buf);
+ }
+
+ p = (struct spl_pbuf *) ADDR_SHTOL(buf->p);
+ buflen = p->tot_len;
+
+ if (mem)
+ {
+ copylen = len > buflen ? buflen : len;
+
+ if ((copylen > 0) && 0 == spl_pbuf_copy_partial(p, mem, copylen, 0))
+ {
+ NSSBR_LOGERR("copy failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EFAULT);
+ return -1;
+ }
+
+ off += copylen;
+ }
+
+ if (sbr_udp_get_from_addr(sk, from, fromlen, buf) != 0)
+ {
+ return -1;
+ }
+
+ if (!(flags & MSG_PEEK))
+ {
+ sbr_get_fd_share(sk)->lastdata = NULL;
+ sbr_com_free_recv_buf(sk, (struct spl_pbuf *) ADDR_SHTOL(buf->p));
+ }
+
+ return off;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_recvfrom
+* Description : recv from
+* Input : sbr_socket_t * sk
+* void * mem
+* size_t len
+* int flags
+* struct sockaddr * from
+* socklen_t * fromlen
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_recvfrom(sbr_socket_t * sk, void *mem, size_t len, int flags,
+ struct sockaddr *from, socklen_t * fromlen)
+{
+ sbr_com_lock_recv(sk);
+ int ret = _sbr_udp_recvfrom(sk, mem, len, flags, from, fromlen);
+ sbr_com_unlock_recv(sk);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_recvdata
+* Description : recv data
+* Input : sbr_socket_t * sk
+* const struct iovec* iov
+* int iovcnt
+* struct spl_netbuf *buf
+* Output : None
+* Return Value : static inline
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_udp_recvdata(sbr_socket_t * sk, const struct iovec *iov, int iovcnt,
+ int flags, struct sockaddr *from, socklen_t * fromlen)
+{
+ sbr_com_lock_recv(sk);
+ if (-1 == _sbr_udp_recvfrom(sk, NULL, 0, MSG_PEEK, from, fromlen))
+ {
+ sbr_com_unlock_recv(sk);
+ return -1;
+ }
+
+ struct spl_netbuf *buf = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata);
+ struct spl_pbuf *p = (struct spl_pbuf *) ADDR_SHTOL(buf->p);
+ u32 buflen = p->tot_len;
+ u32 copylen = 0;
+ u32 offset = 0;
+
+ int i;
+
+ for (i = 0; i < iovcnt; ++i)
+ {
+ if (!iov[i].iov_base || (0 == iov[i].iov_len))
+ {
+ continue;
+ }
+
+ copylen = buflen > iov[i].iov_len ? iov[i].iov_len : buflen;
+ if ((copylen > 0)
+ && 0 == spl_pbuf_copy_partial(p, iov[i].iov_base, copylen,
+ offset))
+ {
+ NSSBR_LOGERR("copy failed]fd=%d", sk->fd);
+ goto done;
+ }
+
+ offset += copylen;
+ buflen -= copylen;
+
+ if (0 == buflen)
+ {
+ goto done;
+ }
+ }
+
+ done:
+ if (!(flags & MSG_PEEK))
+ {
+ sbr_get_fd_share(sk)->lastdata = NULL;
+ sbr_com_free_recv_buf(sk, (struct spl_pbuf *) ADDR_SHTOL(buf->p));
+ }
+
+ sbr_com_unlock_recv(sk);
+ return offset;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_readv
+* Description : readv
+* Input : sbr_socket_t* sk
+* const struct iovec* iov
+* int iovcnt
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_readv(sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ return sbr_udp_recvdata(sk, iov, iovcnt, 0, NULL, NULL);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_recvmsg
+* Description : recv msg
+* Input : sbr_socket_t* sk
+* struct msghdr* msg
+* int flags
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int sbr_udp_recvmsg(sbr_socket_t * sk, struct msghdr *msg, int flags)
+{
+ return sbr_udp_recvdata(sk, msg->msg_iov, msg->msg_iovlen, flags,
+ (struct sockaddr *) msg->msg_name,
+ &msg->msg_namelen);
+}
+
+/*****************************************************************************
+* Prototype : sbr_copy_iov
+* Description : copy iov
+* Input : sbr_socket_t * sk
+* const struct iovec * iov
+* int iovcnt
+* struct spl_pbuf* buf
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_copy_iov(sbr_socket_t * sk, const struct iovec *iov, int iovcnt,
+ struct spl_pbuf *buf)
+{
+ u32 buf_left = buf->len;
+ i8 *buf_data = (i8 *) ADDR_SHTOL(buf->payload);
+ u32 iov_left;
+ i8 *iov_data;
+ u32 copy_len;
+
+ int i;
+
+ for (i = 0; i < iovcnt; ++i)
+ {
+ if (!iov[i].iov_base || (0 == iov[i].iov_len))
+ {
+ continue;
+ }
+
+ iov_left = (u32) iov[i].iov_len; /* to u32 is ok,len is checked in sbr_udp_senddata */
+ iov_data = (i8 *) iov[i].iov_base;
+ while (iov_left)
+ {
+ copy_len = buf_left > iov_left ? iov_left : buf_left;
+
+ if (NULL == common_memcpy(buf_data, iov_data, copy_len))
+ {
+ NSSBR_LOGERR("common_memcpy error]fd=%d", sk->fd);
+ sbr_set_sk_errno(sk, EFAULT);
+ return -1;
+ }
+
+ buf_data += copy_len;
+ buf_left -= copy_len;
+ iov_data += copy_len;
+ iov_left -= copy_len;
+ if (0 == buf_left)
+ {
+ buf = (struct spl_pbuf *) ADDR_SHTOL(buf->next);
+ if (buf)
+ {
+ buf_left = buf->len;
+ buf_data = (i8 *) ADDR_SHTOL(buf->payload);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_senddata
+* Description : send data
+* Input : sbr_socket_t * sk
+* const struct iovec * iov
+* int iovcnt
+* int flags
+* const struct sockaddr * to
+* socklen_t tolen
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_udp_senddata(sbr_socket_t * sk, const struct iovec *iov, int iovcnt,
+ int flags, const struct sockaddr *to, socklen_t tolen)
+{
+ size_t size = 0;
+ int iov_idx;
+
+ for (iov_idx = 0; iov_idx < iovcnt; ++iov_idx)
+ {
+ if ((SPL_MAX_UDP_MSG_LEN - size) < iov[iov_idx].iov_len)
+ {
+ NSSBR_LOGERR
+ ("size > SPL_MAX_UDP_MSG_LEN]fd=%d,SPL_MAX_UDP_MSG_LEN=%u",
+ sk->fd, SPL_MAX_UDP_MSG_LEN);
+ sbr_set_sk_io_errno(sk, EMSGSIZE);
+ return -1;
+ }
+
+ size += iov[iov_idx].iov_len;
+ }
+
+ if (to == NULL)
+ {
+ /* if not bind , then dest address should not be NULL */
+ if (IPADDR_ANY == ss_get_remote_ip(sbr_get_conn(sk))->addr)
+ {
+ NSSBR_LOGERR("dest address is null]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, EDESTADDRREQ);
+ return -1;
+ }
+ }
+ else if (to->sa_family != AF_INET)
+ {
+ NSSBR_LOGERR("invalid address family]fd=%d,family=%d", sk->fd,
+ to->sa_family);
+ sbr_set_sk_io_errno(sk, EAFNOSUPPORT);
+ return -1;
+ }
+ else if (tolen != sizeof(struct sockaddr_in))
+ {
+ NSSBR_LOGERR("invalid address len]fd=%d,tolen=%u", sk->fd, tolen);
+ sbr_set_sk_io_errno(sk, EINVAL);
+ return -1;
+ }
+
+ struct spl_netbuf buf;
+ const struct sockaddr_in *to_in = (const struct sockaddr_in *) to;
+ buf.p = NULL;
+ if (to_in)
+ {
+ NSSBR_LOGDBG("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa(to_in->sin_addr), ntohs(to_in->sin_port),
+ sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk)));
+ inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr);
+ netbuf_fromport(&buf) = ntohs(to_in->sin_port);
+ }
+ else
+ {
+ spl_ip_addr_set_any(&buf.addr);
+ netbuf_fromport(&buf) = 0;
+ }
+
+ spl_ip_addr_t local_ip = { IPADDR_ANY };
+
+ int err = ss_get_last_errno(sbr_get_conn(sk));
+ if (SPL_ERR_IS_FATAL(err))
+ {
+ NS_LOG_CTRL(LOG_CTRL_SEND, LOGSBR, "NSSBR", NSLOG_ERR,
+ "connection fatal error!err=%d", err);
+ sbr_set_sk_errno(sk, sbr_spl_err_to_errno(err));
+ return -1;
+ }
+
+ u16 remain_len = size; //+ head_room_len;
+ struct spl_pbuf *p = NULL;
+ PRIMARY_ADDR struct spl_pbuf *header = NULL;
+ struct spl_pbuf **tail = &header;
+ u16 head_len = L2_L3_ROOM_LEN + L4_ROOM_LEN;
+ u16 copy_len;
+ u16 alloc_len;
+
+ do
+ {
+ copy_len =
+ remain_len >
+ (SPL_PBUF_UDP_LEN - head_len) ? (SPL_PBUF_UDP_LEN -
+ head_len) : remain_len;
+ alloc_len = head_len + copy_len;
+ p = sbr_malloc_tx_pbuf(alloc_len, head_len);
+ if (unlikely(!p))
+ {
+ NSSBR_LOGDBG("malloc pbuf failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno(sk, ENOMEM);
+ sbr_handle_free_send_buf(sk,
+ (struct spl_pbuf *) ADDR_SHTOL(header));
+ // ss_set_send_event(sbr_get_conn(sk), 0);
+ return -1;
+ }
+
+ struct spl_pbuf *tmp = (struct spl_pbuf *) ADDR_SHTOL(header);
+ while (tmp)
+ {
+ tmp->tot_len += p->len;
+ tmp = (struct spl_pbuf *) ADDR_SHTOL(tmp->next);
+ }
+
+ *tail = (struct spl_pbuf *) ADDR_LTOSH(p); /* header will changed to share */
+ tail = &p->next;
+
+ remain_len -= copy_len;
+ head_len = L2_L3_ROOM_LEN;
+ }
+ while (remain_len);
+
+ /*udp support len=0 */
+ if (size != 0)
+ {
+ if (sbr_copy_iov
+ (sk, iov, iovcnt, (struct spl_pbuf *) ADDR_SHTOL(header)) != 0)
+ {
+ sbr_handle_free_send_buf(sk,
+ (struct spl_pbuf *) ADDR_SHTOL(header));
+ return -1;
+ }
+ }
+
+ buf.p = header;
+ err = sbr_handle_udp_send(sk, &buf, &local_ip);
+ if (0 == err)
+ {
+ epoll_triggle_event_from_api(sk, EPOLL_API_OP_SEND);
+ //ss_set_send_event(sbr_get_conn(sk), 1);
+ return size;
+ }
+ else
+ {
+ sbr_handle_free_send_buf(sk, (struct spl_pbuf *) ADDR_SHTOL(buf.p));
+ return -1;
+ }
+
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_sendto
+* Description : sendto
+* Input : sbr_socket_t * sk
+* const void * data
+* size_t size
+* int flags
+* const struct sockaddr * to
+* socklen_t tolen
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_sendto(sbr_socket_t * sk, const void *data, size_t size, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ struct iovec iov;
+
+ iov.iov_base = (void *) data;
+ iov.iov_len = size;
+ return sbr_udp_senddata(sk, &iov, 1, flags, to, tolen);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_send
+* Description : send
+* Input : sbr_socket_t * sk
+* const void * data
+* size_t size
+* int flags
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_send(sbr_socket_t * sk, const void *data, size_t size, int flags)
+{
+ return sk->fdopt->sendto(sk, data, size, flags, NULL, 0);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_sendmsg
+* Description : send msg
+* Input : sbr_socket_t * sk
+* const struct msghdr * pmsg
+* int flags
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_sendmsg(sbr_socket_t * sk, const struct msghdr *pmsg, int flags)
+{
+ return sbr_udp_senddata(sk, pmsg->msg_iov, pmsg->msg_iovlen, flags,
+ (struct sockaddr *) pmsg->msg_name,
+ pmsg->msg_namelen);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_writev
+* Description : writev
+* Input : sbr_socket_t * sk
+* const struct iovec * iov
+* int iovcnt
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_writev(sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ return sbr_udp_senddata(sk, iov, iovcnt, 0, NULL, 0);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_fcntl
+* Description : fcntl
+* Input : sbr_socket_t * sk
+* int cmd
+* long arg
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int sbr_udp_fcntl(sbr_socket_t * sk, int cmd, long arg)
+{
+ int ret = 0;
+
+ switch (cmd)
+ {
+ case F_GETFL:
+ ret = ss_get_nonblock_flag(sbr_get_conn(sk));
+ NSSBR_LOGDBG("F_GETFL]fd=%d,ret=%d", sk->fd, ret);
+ break;
+ case F_SETFL:
+ if (arg & O_NONBLOCK)
+ {
+ NSSBR_LOGDBG("F_SETFL set O_NONBLOCK val]fd=%d,arg=%ld",
+ sk->fd, arg);
+ ss_set_nonblock_flag(sbr_get_conn(sk), (arg & O_NONBLOCK));
+ }
+ else
+ {
+ NSSBR_LOGDBG("F_SETFL clean O_NONBLOCK val]fd=%d,arg=%ld",
+ sk->fd, arg);
+ ss_set_nonblock_flag(sbr_get_conn(sk), 0);
+ }
+
+ break;
+ default:
+ NSSBR_LOGERR("cmd is not support]fd=%d,cmd=%d", sk->fd, cmd);
+ ret = -1;
+ sbr_set_sk_errno(sk, EINVAL);
+
+ break;
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_ioctl
+* Description : ioctl
+* Input : sbr_socket_t * sk
+* unsigned long cmd
+* void * arg
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int sbr_udp_ioctl(sbr_socket_t * sk, unsigned long cmd, void *arg)
+{
+ int ret = 0;
+
+ switch (cmd)
+ {
+ case FIONREAD:
+ {
+ if (!sbr_com_try_lock_recv(sk))
+ {
+ return 0;
+ }
+
+ struct spl_pbuf *p = NULL;
+ struct spl_netbuf *buf = NULL;
+ if (!sbr_get_fd_share(sk)->lastdata)
+ {
+ ret = sbr_udp_recv_from_ring(sk, &buf, -1);
+ if (ret != 0)
+ {
+ sbr_com_unlock_recv(sk);
+ return EWOULDBLOCK == errno ? 0 : -1;
+ }
+
+ sbr_get_fd_share(sk)->lastdata = (void *) ADDR_LTOSH(buf);
+ p = (struct spl_pbuf *) ADDR_SHTOL(buf->p);
+ }
+ else
+ {
+ buf =
+ (struct spl_netbuf *)
+ ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata);
+ p = (struct spl_pbuf *) ADDR_SHTOL(buf->p);
+ }
+
+ *((u32 *) arg) = p->tot_len;
+ sbr_com_unlock_recv(sk);
+ }
+ break;
+ case FIONBIO:
+ {
+ u8 val = 0;
+
+ if (arg && *(u32 *) arg)
+ {
+ val = 1;
+ }
+
+ ss_set_nonblock_flag(sbr_get_conn(sk), val);
+ NSSBR_LOGDBG("FIONBIO]fd=%d,val=%u", sk->fd, val);
+ }
+ break;
+ default:
+ {
+ NSSBR_LOGERR("cmd is not support]fd=%d,cmd=%lu", sk->fd, cmd);
+ ret = -1;
+ sbr_set_sk_errno(sk, ENOTTY);
+ }
+
+ break;
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_close
+* Description : close
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int sbr_udp_close(sbr_socket_t * sk)
+{
+ if (sbr_get_fd_share(sk)->lastdata)
+ {
+ struct spl_netbuf *buf = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata);
+ struct spl_pbuf *p = (struct spl_pbuf *) ADDR_SHTOL(buf->p);
+ sbr_com_free_recv_buf(sk, p);
+ }
+
+ /* if failed,free it in recycle */
+ return sbr_handle_close(sk, 0);
+}
+
+sbr_fdopt udp_fdopt = {
+ .socket = sbr_udp_socket,
+ .bind = sbr_udp_bind,
+ .listen = sbr_udp_listen,
+ .accept = sbr_udp_accept,
+ .accept4 = sbr_udp_accept4,
+ .connect = sbr_udp_connect,
+ .shutdown = sbr_udp_shutdown,
+ .getsockname = sbr_udp_getsockname,
+ .getpeername = sbr_udp_getpeername,
+ .getsockopt = sbr_udp_getsockopt,
+ .setsockopt = sbr_udp_setsockopt,
+ .recvfrom = sbr_udp_recvfrom,
+ .readv = sbr_udp_readv,
+ .recvmsg = sbr_udp_recvmsg,
+ .send = sbr_udp_send,
+ .sendto = sbr_udp_sendto,
+ .sendmsg = sbr_udp_sendmsg,
+ .writev = sbr_udp_writev,
+ .fcntl = sbr_udp_fcntl,
+ .ioctl = sbr_udp_ioctl,
+ .close = sbr_udp_close,
+ .peak = sbr_com_peak,
+ .lock_common = sbr_com_lock_common,
+ .unlock_common = sbr_com_unlock_common,
+ .fork_parent = sbr_com_fork_parent,
+ .fork_child = sbr_com_fork_child,
+ .ep_getevt = stackx_eventpoll_getEvt,
+ .ep_triggle = stackx_eventpoll_triggle,
+ .set_close_stat = NULL,
+};