Explorar el Código

add: network,net_lwip2,临时保存tcpserver一对多的功能

未完成的状态, 仍需大改

https://gitee.com/openLuat/LuatOS/issues/ICXESQ
Wendal Chen hace 4 meses
padre
commit
18e153a75d

+ 24 - 11
components/network/adapter/luat_lib_socket.c

@@ -945,24 +945,29 @@ static int l_socket_listen(lua_State *L)
 	int result = network_listen(l_ctrl->netc, 0);
 	lua_pushboolean(L, (result < 0)?0:1);
 	lua_pushboolean(L, result == 0);
+	if (result < 0) {
+		LLOGE("listen fail %d", result);
+	}
 	return 2;
 }
 
 /*
-作为服务端接收到一个新的客户端,注意,如果是类似W5500的硬件协议栈不支持1对多,则不需要第二个参数
-@api socket.accept(ctrl)
+作为服务端接收到一个新的客户端
+@api socket.accept(ctrl, args)
 @user_data socket.create得到的ctrl,这里是服务器端
 @string or function or nil string为消息通知的taskName,function则为回调函数,和socket.create参数一致
 @return boolean true没有异常发生,false失败了,如果false则不需要看下一个返回值了,如果false,后续要close
 @return user_data or nil 如果支持1对多,则会返回新的ctrl,自动create,如果不支持则返回nil
 @usage 
 local succ, new_netc = socket.accept(ctrl, cb)
+-- 注意, 当目标适配器不支持1对多时,new_netc会是nil, 第二个参数无效
+-- 当第二个参数为nil时, 固定为一对一模式, new_netc也会是nil
 */
 static int l_socket_accept(lua_State *L)
 {
 	luat_socket_ctrl_t *old_ctrl = l_get_ctrl(L, 1);
 	if (!old_ctrl) return 0;
-	if (network_accept_enable(old_ctrl->netc))
+	if ((lua_isfunction(L, 2) || lua_isstring(L, 2)) && network_accept_enable(old_ctrl->netc))
 	{
 		luat_socket_ctrl_t *new_ctrl = (luat_socket_ctrl_t *)lua_newuserdata(L, sizeof(luat_socket_ctrl_t));
 		if (!new_ctrl)
@@ -997,19 +1002,27 @@ static int l_socket_accept(lua_State *L)
 			memset(new_ctrl->task_name, 0, len + 1);
 			memcpy(new_ctrl->task_name, buf, len);
 		}
-		if (network_socket_accept(old_ctrl, new_ctrl))
-		{
+		else {
+			LLOGE("accept模式必须传入回调函数或taskName");
+			network_release_ctrl(new_ctrl->netc);
+			new_ctrl->netc = NULL;
 			lua_pushboolean(L, 0);
-			lua_pushnil(L);
-			return 2;
+			return 1;
 		}
-		else
+		if (network_socket_accept(old_ctrl->netc, new_ctrl->netc))
 		{
-			lua_pushboolean(L, 1);
-			luaL_setmetatable(L, LUAT_NW_CTRL_TYPE);
+			network_release_ctrl(new_ctrl->netc);
+			new_ctrl->netc = NULL;
+			lua_pushboolean(L, 0);
+			lua_pushnil(L);
 			return 2;
 		}
-
+		// 恢复到可监听状态
+		LLOGD("accept success %p", new_ctrl->netc);
+		luaL_setmetatable(L, LUAT_NW_CTRL_TYPE);
+		lua_pushboolean(L, 1);
+		lua_pushvalue(L, -2);
+		return 2;
 	}
 	else
 	{

+ 22 - 2
components/network/adapter/luat_network_adapter.c

@@ -1627,13 +1627,23 @@ uint8_t network_accept_enable(network_ctrl_t *ctrl)
 int network_socket_accept(network_ctrl_t *ctrl, network_ctrl_t *accept_ctrl)
 {
 	network_adapter_t *adapter = &prv_adapter_table[ctrl->adapter_index];
-	if (adapter->opt->no_accept)
+	if (adapter->opt == NULL) {
+		DBG_ERR("adapter %d not register!", ctrl->adapter_index);
+		return -1;
+	}
+	if (adapter->opt->no_accept || accept_ctrl == NULL)
 	{
 //		DBG("%x,%d,%llu,%x,%x,%x",adapter->opt->socket_accept, ctrl->socket_id, ctrl->tag, &ctrl->remote_ip, &ctrl->remote_port, adapter->user_data);
 		adapter->opt->socket_accept(ctrl->socket_id, ctrl->tag, &ctrl->remote_ip, &ctrl->remote_port, adapter->user_data);
 		return 0;
 	}
-	accept_ctrl->socket_id = adapter->opt->socket_accept(ctrl->socket_id, ctrl->tag, &accept_ctrl->remote_ip, &accept_ctrl->remote_port, adapter->user_data);
+	if (adapter->opt->socket_accept == NULL)
+	{
+		DBG_ERR("adapter %d not support accept multiple", ctrl->adapter_index);
+		return -1;
+	}
+	DBG_ERR("执行accept操作 %p %p", adapter, accept_ctrl, adapter->opt->socket_accept);
+	accept_ctrl->socket_id = adapter->opt->socket_accept(ctrl->socket_id, 0, &accept_ctrl->remote_ip, &accept_ctrl->remote_port, accept_ctrl);
 	if (accept_ctrl->socket_id < 0)
 	{
 		return -1;
@@ -1648,6 +1658,10 @@ int network_socket_accept(network_ctrl_t *ctrl, network_ctrl_t *accept_ctrl)
 		accept_ctrl->tcp_timeout_ms = ctrl->tcp_timeout_ms;
 		accept_ctrl->local_port = ctrl->local_port;
 		accept_ctrl->state = NW_STATE_ONLINE;
+		DBG_ERR("accept_ctrl %p tag: %llu", accept_ctrl, accept_ctrl->tag);
+		// 将srv恢复到可接收的状态
+		ctrl->state = NW_STATE_LISTEN;
+		ctrl->wait_target_state = NW_WAIT_ON_LINE;
 		return 0;
 	}
 }
@@ -2192,6 +2206,12 @@ int network_listen(network_ctrl_t *ctrl, uint32_t timeout_ms)
 	}
 	if (ctrl->socket_id >= 0)
 	{
+		if (network_accept_enable(ctrl))
+		{
+			DBG("socket %d is accept enable", ctrl->socket_id);
+			return 1;
+		}
+		DBG_ERR("listen but socket_id(%d) >= 0, state %d", ctrl->socket_id, ctrl->state);
 		return -1;
 	}
 	NW_LOCK;

+ 96 - 19
components/network/adapter_lwip2/net_lwip2.c

@@ -203,6 +203,7 @@ static void net_lwip2_callback_to_nw_task(uint8_t adapter_index, uint32_t event_
 		prvlwip.socket_busy &= ~(1 << param1);
 		break;
 	}
+	LLOGD("socket_cb event_id %08X param.tag %d param3 %ld", event_id, param.tag, param3);
 	prvlwip.socket_cb(&event, &param);
 }
 
@@ -411,6 +412,7 @@ static err_t net_lwip2_tcp_fast_accept_cb(void *arg, struct tcp_pcb *newpcb, err
 {
 	int socket_id = ((uint32_t)arg) & 0x0000ffff;
 	uint8_t adapter_index = ((uint32_t)arg) >> 16;
+	LLOGD("adapter %d socket %d new client", adapter_index, socket_id);
 	if (err || !newpcb)
 	{
 		net_lwip2_tcp_error(adapter_index, socket_id);
@@ -840,6 +842,11 @@ static void net_lwip2_task(void *param)
 		// LLOGD("event dns query 3");
 		break;
 	case EV_LWIP_SOCKET_LISTEN:
+		if (prvlwip.socket[socket_id].listen_tcp) {
+			// 已经在监听了, 不需要重复操作, 发送事件就行
+			net_lwip2_callback_to_nw_task(adapter_index, EV_NW_SOCKET_LISTEN, socket_id, 0, 0);
+			break;
+		}
 		if (!prvlwip.socket[socket_id].in_use || !prvlwip.socket[socket_id].pcb.ip)
 		{
 			NET_DBG("adapter %d socket %d cannot use! %d,%x", adapter_index, socket_id, prvlwip.socket[socket_id].in_use, prvlwip.socket[socket_id].pcb.ip);
@@ -1038,9 +1045,18 @@ static void net_lwip2_check_network_ready(uint8_t adapter_index)
 static int net_lwip2_check_socket(void *user_data, int socket_id, uint64_t tag)
 {
 	if ((uint32_t)user_data >= NW_ADAPTER_INDEX_LWIP_NETIF_QTY) return -1;
-	if (socket_id >= MAX_SOCK_NUM) return -1;
-	if (prvlwip.socket[socket_id].tag != tag) return -1;
-	if (!prvlwip.socket[socket_id].in_use || prvlwip.socket[socket_id].state) return -1;
+	if (socket_id >= MAX_SOCK_NUM) {
+		LLOGD("socket id 超出范围 %d", socket_id);
+		return -1;
+	}
+	if (prvlwip.socket[socket_id].tag != tag) {
+		LLOGD("socket tag 不匹配 %llx != %llx", prvlwip.socket[socket_id].tag, tag);
+		return -1;
+	}
+	if (!prvlwip.socket[socket_id].in_use || prvlwip.socket[socket_id].state) {
+		LLOGD("socket 状态不正确 %d,%d,%d", socket_id, prvlwip.socket[socket_id].in_use, prvlwip.socket[socket_id].state);
+		return -1;
+	}
 	return 0;
 }
 
@@ -1156,14 +1172,9 @@ static void net_lwip2_create_socket_now(uint8_t adapter_index, uint8_t socket_id
 	}
 }
 
-static int net_lwip2_create_socket(uint8_t is_tcp, uint64_t *tag, void *param, uint8_t is_ipv6, void *user_data)
-{
-	// uint8_t index = (uint32_t)user_data;
-	uint8_t adapter_index = (uint32_t)user_data;
-	if ((uint32_t)adapter_index >= NW_ADAPTER_INDEX_LWIP_NETIF_QTY) return 0;
-	int i, socket_id;
-	socket_id = -1;
-	// OS_LOCK;
+static int gen_next_socket_id() {
+	int socket_id = -1;
+	int i;
 	if (!prvlwip.socket[prvlwip.next_socket_index].in_use)
 	{
 		socket_id = prvlwip.next_socket_index;
@@ -1185,6 +1196,16 @@ static int net_lwip2_create_socket(uint8_t is_tcp, uint64_t *tag, void *param, u
 	{
 		prvlwip.next_socket_index = 0;
 	}
+	return socket_id;
+}
+
+static int net_lwip2_create_socket(uint8_t is_tcp, uint64_t *tag, void *param, uint8_t is_ipv6, void *user_data)
+{
+	// uint8_t index = (uint32_t)user_data;
+	uint8_t adapter_index = (uint32_t)user_data;
+	if ((uint32_t)adapter_index >= NW_ADAPTER_INDEX_LWIP_NETIF_QTY) return 0;
+	int socket_id = gen_next_socket_id();
+	// OS_LOCK;
 	if (socket_id >= 0)
 	{
 		LWIP_ASSERT("socket must free before create", !prvlwip.socket[socket_id].pcb.ip);
@@ -1239,14 +1260,68 @@ static int net_lwip2_socket_listen(int socket_id, uint64_t tag,  uint16_t local_
 	return 0;
 }
 //作为server接受一个client
-static int net_lwip2_socket_accept(int socket_id, uint64_t tag,  luat_ip_addr_t *remote_ip, uint16_t *remote_port, void *user_data)
+static int net_lwip2_socket_accept(int srv_socket_id, uint64_t srv_tag,  luat_ip_addr_t *remote_ip, uint16_t *remote_port, void *user_data)
 {
-	int result = net_lwip2_check_socket(user_data, socket_id, tag);
-	if (result) return result;
-	uint8_t adapter_index = (uint32_t)user_data;
-	if (adapter_index >= NW_ADAPTER_INDEX_LWIP_NETIF_QTY) return -1;
-	*remote_ip = prvlwip.socket[socket_id].pcb.tcp->remote_ip;
-	*remote_port = prvlwip.socket[socket_id].pcb.tcp->remote_port;
+	if (srv_tag == 0) {
+		uint64_t tag = 0;
+		LLOGD("accept tag 0, one to many");
+		if (prvlwip.socket[srv_socket_id].pcb.tcp == NULL) {
+			LLOGE("accept fail, srv socket not in wait-accept state");
+			return -1;
+		}
+		// 首先,分配新的socket id
+		int socket_id = gen_next_socket_id();
+		if (socket_id < 0) {
+			LLOGE("accept fail, too many socket");
+			return -1;
+		}
+		network_ctrl_t* accept_ctrl = (network_ctrl_t*)user_data;
+		// 然后, 把新的socket和老的socket绑定在一起
+		prvlwip.socket_busy &= (1 << socket_id);
+		prvlwip.socket_connect &= (1 << socket_id);
+		prvlwip.socket_tag++;
+		tag = prvlwip.socket_tag;
+		accept_ctrl->tag = tag;
+		prvlwip.socket[socket_id].in_use = 1;
+		prvlwip.socket[socket_id].tag = tag;
+		prvlwip.socket[socket_id].param = accept_ctrl;
+		prvlwip.socket[socket_id].is_tcp = 1;
+
+		LLOGI("accept new socket %d from srv socket %d", socket_id, srv_socket_id);
+		LLOGD("accept srv tag %llx, new tag %llx accept_ctrl->tag %llx", srv_tag, tag, accept_ctrl->tag);
+
+		//--------------------
+		// 把srv暂存的pcb给新的socket
+		prvlwip.socket[socket_id].pcb.tcp = prvlwip.socket[srv_socket_id].pcb.tcp;
+		prvlwip.socket[srv_socket_id].pcb.tcp = NULL; // 恢复成老的监听状态
+		prvlwip.socket[srv_socket_id].rx_wait_size = 0;
+		prvlwip.socket[srv_socket_id].tx_wait_size = 0;
+		//--------------------
+
+		PV_Union uPV;
+        uPV.u16[0] = socket_id;
+        uPV.u16[1] = accept_ctrl->adapter_index;
+		prvlwip.socket[socket_id].pcb.tcp->callback_arg = uPV.p;
+		llist_traversal(&prvlwip.socket[socket_id].wait_ack_head, net_lwip2_del_data_cache, NULL);
+		llist_traversal(&prvlwip.socket[socket_id].tx_head, net_lwip2_del_data_cache, NULL);
+		llist_traversal(&prvlwip.socket[socket_id].rx_head, net_lwip2_del_data_cache, NULL);
+		*remote_ip = prvlwip.socket[socket_id].pcb.tcp->remote_ip;
+		*remote_port = prvlwip.socket[socket_id].pcb.tcp->remote_port;
+
+		// 把srv_socket_id的对应的状态恢复好
+
+		return socket_id;
+	}
+	else {
+		// 一对一的情况, 兼容老的
+		int socket_id = srv_socket_id;
+		int result = net_lwip2_check_socket(user_data, socket_id, srv_tag);
+		if (result) return result;
+		uint8_t adapter_index = (uint32_t)user_data;
+		if (adapter_index >= NW_ADAPTER_INDEX_LWIP_NETIF_QTY) return -1;
+		*remote_ip = prvlwip.socket[socket_id].pcb.tcp->remote_ip;
+		*remote_port = prvlwip.socket[socket_id].pcb.tcp->remote_port;
+	}
 	return 0;
 }
 //主动断开一个tcp连接,需要走完整个tcp流程,用户需要接收到close ok回调才能确认彻底断开
@@ -1364,6 +1439,7 @@ static int net_lwip2_socket_receive(int socket_id, uint64_t tag,  uint8_t *buf,
 static int net_lwip2_socket_send(int socket_id, uint64_t tag, const uint8_t *buf, uint32_t len, int flags, luat_ip_addr_t *remote_ip, uint16_t remote_port, void *user_data)
 {
 	int result = net_lwip2_check_socket(user_data, socket_id, tag);
+	// LLOGD("net_lwip2_socket_send check result %d socket %d", result, socket_id);
 	if (result) return result;
 	
 	uint8_t adapter_index = (uint32_t)user_data;
@@ -1372,6 +1448,7 @@ static int net_lwip2_socket_send(int socket_id, uint64_t tag, const uint8_t *buf
 	uint32_t save_len = 0;
 	uint32_t dummy_len = 0;
 	socket_data_t *p;
+	// LLOGD("socket %d send len %d", socket_id, len);
 	if (prvlwip.socket[socket_id].is_tcp)
 	{
 		while(save_len < len)
@@ -1614,7 +1691,7 @@ static const network_adapter_info prv_net_lwip2_adapter =
 		.socket_set_callback = net_lwip2_socket_set_callback,
 		.name = "lwip",
 		.max_socket_num = MAX_SOCK_NUM,
-		.no_accept = 1,
+		.no_accept = 0,
 		.is_posix = 1,
 		.check_ack = net_lwip2_check_ack
 };

+ 52 - 0
olddemo/socket/tcp_server_mulit/main.lua

@@ -0,0 +1,52 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "tcpserver"
+VERSION = "1.0.0"
+
+
+srv = require("tcpsrv")
+
+-- 统一联网函数
+sys.taskInit(function()
+    -----------------------------
+    -- 统一联网函数, 可自行删减
+    ----------------------------
+    if wlan and wlan.connect then
+        -- wifi 联网, ESP32系列均支持, 要根据实际情况修改ssid和password!!
+        local ssid = "uiot"
+        local password = "czcjhp1985cbm"
+        log.info("wifi", ssid, password)
+        -- TODO 改成自动配网
+        wlan.init()
+        -- wlan.setMode(wlan.STATION) -- 默认也是这个模式,不调用也可以
+        wlan.connect(ssid, password, 1)
+    elseif mobile then
+        -- EC618系列, 如Air780E/Air600E/Air700E
+        -- mobile.simid(2) -- 自动切换SIM卡, 按需启用
+        -- 模块默认会自动联网, 无需额外的操作
+    elseif socket then
+        -- 适配了socket库也OK, 就当1秒联网吧
+        sys.timerStart(sys.publish, 1000, "IP_READY")
+    else
+        -- 其他不认识的bsp, 循环提示一下吧
+        while 1 do
+            sys.wait(1000)
+            log.info("bsp", "本bsp可能未适配网络层, 请查证")
+        end
+    end
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready")
+end)
+
+sys.taskInit(function()
+    sys.waitUntil("net_ready")
+    log.info("联网完成", "准备启动tcp server")
+    sys.wait(1000)
+    SerDemo(1080)
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 60 - 0
olddemo/socket/tcp_server_mulit/tcpsrv.lua

@@ -0,0 +1,60 @@
+local libnet = require "libnet"
+
+--下面演示用阻塞方式做自动应答服务器,只适合W5500
+local dName = "D2_TASK"
+local function netCB(msg)
+	log.info("未处理消息", msg[1], msg[2], msg[3], msg[4])
+end
+
+local function serTask(port, adapter)
+	log.info("tcpsrv", "准备监听端口", socket.localIP(adapter), port)
+	local tx_buff = zbuff.create(1024)
+	local rx_buff = zbuff.create(1024)
+	local netc 
+	local result, param, succ, rIP, rPort
+	netc = socket.create(adapter, dName)
+	socket.debug(netc, true)
+	socket.config(netc, port)
+	log.info("netc", netc)
+	-- result = libnet.waitLink(dName, 0, netc)
+	clients = {}
+	local buff = zbuff.create(1024)
+	while true do
+		log.info("开始监听客户端连接, 无限时长")
+		sys.wait(1000)
+		result, code = libnet.listen(dName, 0, netc)
+		log.info("监听结果", result, code)
+		if result then
+			log.info("有客户端连接请求到来, 接受连接")
+            result, client = socket.accept(netc, function(client, event, param)
+				log.info("客户端事件", client, event, params)
+				if event == socket.EVENT then
+					local result = socket.rx(client, buff)
+					log.info("客户端数据到来", result, buff:used())
+					buff:seek(0)
+				end
+			end)
+			socket.debug(client, true)
+            if result then
+				table.insert(clients, client)
+			    log.info("客户端连上了", client, "发送个问候")
+			    log.info("发送数据", socket.tx(client, "helloworld"))
+            end
+		end
+		sys.wait(1000)
+	end
+	libnet.close(dName, 5000, netc)
+	log.info("服务器关闭了")
+end
+
+
+function SerDemo(port, adapter)
+	sysplus.taskInitEx(serTask, dName, netCB, port, adapter)
+end
+
+-- sys.taskInit(function()
+-- 	while 1 do
+-- 		sys.wait(1000)
+-- 		log.info("meminfo", rtos.meminfo("sys"))
+-- 	end
+-- end)