Browse Source

change: httpsrv,相关lwip操作都放lwip线程,但依然死机,就很无语了

Wendal Chen 9 months ago
parent
commit
ea80865a5f

+ 4 - 2
components/network/httpsrv/inc/luat_httpsrv.h

@@ -11,6 +11,7 @@ typedef struct luat_httpsrv_ctx
     void* userdata;
     uint8_t adapter_id;
     struct netif* netif;
+    struct tcp_pcb* pcb;
 }luat_httpsrv_ctx_t;
 
 
@@ -59,6 +60,7 @@ static const ct_reg_t ct_regs[] = {
     {"bin",     "application/octet-stream"},
 };
 
-
-int luat_httpsrv_stop(int port);
+int luat_httpsrv_start(luat_httpsrv_ctx_t* ctx);
+int luat_httpsrv_free(luat_httpsrv_ctx_t* ctx);
+int luat_httpsrv_stop(luat_httpsrv_ctx_t* ctx);
 int luat_httpsrv_start(luat_httpsrv_ctx_t* ctx);

+ 54 - 22
components/network/httpsrv/src/luat_httpsrv_lwip.c

@@ -18,10 +18,12 @@
 
 #include "http_parser.h"
 
+#undef LLOGD
+#define LLOGD(...) 
 
 typedef struct client_socket_ctx
 {
-    // int id;
+    int lua_ref_id;
     int code;
     struct http_parser parser;
 
@@ -43,9 +45,6 @@ typedef struct client_socket_ctx
     uint8_t write_done;
 }client_socket_ctx_t;
 
-static struct tcp_pcb* srvpcb;
-static int lua_ref_id;
-
 static int handle_static_file(client_socket_ctx_t *client);
 
 static void client_cleanup(client_socket_ctx_t *client);
@@ -180,7 +179,7 @@ static void client_cleanup(client_socket_ctx_t *client) {
 
 static int luat_client_cb(lua_State* L, void* ptr) {
     client_socket_ctx_t* client = (client_socket_ctx_t*)ptr;
-    lua_geti(L, LUA_REGISTRYINDEX, lua_ref_id);
+    lua_geti(L, LUA_REGISTRYINDEX, client->lua_ref_id);
     if (lua_isnil(L, -1)) {
         client_cleanup(client);
         return 0;
@@ -373,7 +372,7 @@ static void client_err_cb(void *arg, err_t err) {
 }
 
 static err_t srv_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) {
-    (void)arg;
+    luat_httpsrv_ctx_t* srvctx = (luat_httpsrv_ctx_t*) arg;
     if (err) {
         LLOGD("accpet err %d", err);
         tcp_abort(newpcb);
@@ -388,6 +387,7 @@ static err_t srv_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) {
     tcp_accepted(newpcb);
     memset(ctx, 0, sizeof(client_socket_ctx_t));
     ctx->pcb = newpcb;
+    ctx->lua_ref_id = srvctx->lua_ref_id;
     tcp_arg(newpcb, ctx);
     tcp_recv(newpcb, client_recv_cb);
     tcp_sent(newpcb, client_sent_cb);
@@ -395,37 +395,69 @@ static err_t srv_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) {
     return ERR_OK;
 }
 
-int luat_httpsrv_stop(int port) {
-    (void)port;
-    if (srvpcb != NULL) {
-        tcp_close(srvpcb);
-        srvpcb = NULL;
+static void srv_stop_cb(void* arg) {
+    luat_httpsrv_ctx_t* ctx = (luat_httpsrv_ctx_t*)arg;
+    if (ctx == NULL) {
+        return;
+    }
+    if (ctx->pcb) {
+        tcp_abort(ctx->pcb);
+        tcp_close(ctx->pcb);
+        ctx->pcb = NULL;
     }
+    luat_httpsrv_free(ctx);
+}
+int luat_httpsrv_stop(luat_httpsrv_ctx_t* ctx) {
+    tcpip_callback(srv_stop_cb, ctx);
     return 0;
 }
 
-int luat_httpsrv_start(luat_httpsrv_ctx_t* ctx) {
-    if (srvpcb != NULL) {
-        LLOGE("only allow 1 httpsrv");
-        return -10;
-    }
+static void luat_httpsrv_start_cb(luat_httpsrv_ctx_t* ctx) {
     struct tcp_pcb* tcp = tcp_new();
     int ret = 0;
     if (tcp == NULL) {
         LLOGD("out of memory when malloc httpsrv tcp_pcb");
-        return -1;
+        return;
     }
     tcp->flags |= SOF_REUSEADDR;
     ret = tcp_bind(tcp, &ctx->netif->ip_addr, ctx->port);
     if (ret) {
         LLOGD("httpsrv bind port %d ret %d", ctx->port);
-        return -2;
+        return;
+    }
+    ctx->pcb = tcp_listen_with_backlog(tcp, 1);
+    tcp_arg(ctx->pcb, ctx);
+    tcp_accept(ctx->pcb, srv_accept_cb);
+    return;
+}
+
+luat_httpsrv_ctx_t* luat_httpsrv_malloc(int port, int adapter_index) {
+    luat_httpsrv_ctx_t* ctx = luat_heap_malloc(sizeof(luat_httpsrv_ctx_t));
+    if (ctx == NULL) {
+        LLOGD("out of memory when malloc httpsrv ctx");
+        return NULL;
     }
-    lua_ref_id = ctx->lua_ref_id;
-    srvpcb = tcp_listen(tcp);
-    tcp_arg(srvpcb, NULL);
-    tcp_accept(srvpcb, srv_accept_cb);
+    memset(ctx, 0, sizeof(luat_httpsrv_ctx_t));
+    ctx->port = port;
+    ctx->adapter_id = adapter_index;
+    return ctx;
+}
+
+int luat_httpsrv_free(luat_httpsrv_ctx_t* ctx) {
+    if (ctx == NULL) {
+        return 0;
+    }
+    luat_heap_free(ctx);
+    ctx = NULL;
     return 0;
+} 
+
+int luat_httpsrv_start(luat_httpsrv_ctx_t* ctx) {
+    int ret = tcpip_callback(luat_httpsrv_start_cb, ctx);
+    if (ret) {
+        LLOGE("启动失败 %d", ret);
+    }
+    return ret;
 }
 
 // 静态文件的处理

+ 65 - 9
components/network/httpsrv/src/luat_lib_httpsrv.c

@@ -17,6 +17,18 @@
 #define LUAT_LOG_TAG "httpsrv"
 #include "luat_log.h"
 
+#define LUAT_HTTPSRV_COUNT 16
+
+typedef struct port_srv
+{
+    uint16_t port;
+    uint8_t adapter;
+    uint8_t status;
+    luat_httpsrv_ctx_t* ctx;
+}port_srv_t;
+
+static port_srv_t srvs[LUAT_HTTPSRV_COUNT];
+
 /*
 启动并监听一个http端口
 @api httpsrv.start(port, func, adapter)
@@ -58,23 +70,48 @@ static int l_httpsrv_start(lua_State *L) {
         LLOGW("httpsrv need callback function!!!");
         return 0;
     }
-    luat_httpsrv_ctx_t ctx = {
-        .port = port
-    };
     uint8_t adapter_index = luaL_optinteger(L, 3, network_get_last_register_adapter());
-    ctx.adapter_id = adapter_index;
     luat_netdrv_t* drv = luat_netdrv_get(adapter_index);
     if (drv == NULL || drv->netif == NULL) {
         LLOGW("该网络还没准备好 %d", adapter_index);
         return 0;
     }
-    ctx.netif = drv->netif;
+    // 检查一下是否有空位
+    for (size_t i = 0; i < LUAT_HTTPSRV_COUNT; i++)
+    {
+        if (srvs[i].port == port && srvs[i].adapter == adapter_index) {
+            LLOGW("httpsrv port %d already in use", port);
+            return 0;
+        }
+    }
+    int index = -1;
+    for (size_t i = 0; i < LUAT_HTTPSRV_COUNT; i++)
+    {
+        if (srvs[i].ctx == NULL) {
+            index = i;
+            break;
+        }
+    }
+    if (index < 0) {
+        LLOGW("httpsrv no free slot, max %d", LUAT_HTTPSRV_COUNT);
+        return 0;
+    }
+
+    luat_httpsrv_ctx_t* ctx = luat_httpsrv_malloc(port, adapter_index);
+    if (ctx == NULL) {
+        return 0;
+    }
+    ctx->netif = drv->netif;
     lua_pushvalue(L, 2);
-    ctx.lua_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
-    int ret = luat_httpsrv_start(&ctx);
+    ctx->lua_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
+    int ret = luat_httpsrv_start(ctx);
     if (ret == 0) {
         ipaddr_ntoa_r(&drv->netif->ip_addr, buff,  32);
-        LLOGI("http listen at %s:%d", buff, ctx.port);
+        LLOGI("http listen at %s:%d", buff, ctx->port);
+        srvs[index].port = port;
+        srvs[index].adapter = adapter_index;
+        srvs[index].ctx = ctx;
+        srvs[index].status = 1;
     }
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 1;
@@ -88,7 +125,26 @@ static int l_httpsrv_start(lua_State *L) {
 */
 static int l_httpsrv_stop(lua_State *L) {
     int port = luaL_checkinteger(L, 1);
-    luat_httpsrv_stop(port);
+    uint8_t adapter_index = luaL_optinteger(L, 3, network_get_last_register_adapter());
+    for (size_t i = 0; i < LUAT_HTTPSRV_COUNT; i++)
+    {
+        if (srvs[i].port == port && srvs[i].adapter == adapter_index) {
+            if (srvs[i].ctx != NULL) {
+                srvs[i].port = 0;
+                srvs[i].adapter = 0;
+                srvs[i].status = 0;
+
+                if (srvs[i].ctx->lua_ref_id != LUA_NOREF) {
+                    luaL_unref(L, LUA_REGISTRYINDEX, srvs[i].ctx->lua_ref_id);
+                    srvs[i].ctx->lua_ref_id = LUA_NOREF;
+                }
+                luat_httpsrv_stop(srvs[i].ctx);
+                srvs[i].ctx = NULL;
+                lua_pushboolean(L, 1);
+                return 1;
+            }
+        }
+    }
     return 0;
 }
 

+ 1 - 1
components/network/libhttp/luat_lib_http.c

@@ -237,7 +237,7 @@ static int l_http_request(lua_State *L) {
 	}
 	#ifdef LUAT_USE_FOTA
 	if (http_ctrl->timeout < 1000 && http_ctrl->isfota) {
-		http_ctrl->timeout = HTTP_TIMEOUT;
+		http_ctrl->timeout = HTTP_TIMEOUT * 2;
 	}
 	#endif
 	if (http_ctrl->timeout < 1000) {

+ 11 - 0
components/network/netdrv/src/luat_netdrv.c

@@ -179,12 +179,23 @@ uint16_t alg_tcpudphdr_chksum(uint32_t src_addr, uint32_t dst_addr, uint8_t prot
 
 void luat_netdrv_netif_input(void* args) {
     netdrv_pkg_msg_t* ptr = (netdrv_pkg_msg_t*)args;
+    if (ptr == NULL) {
+        return;
+    }
+    if (ptr->len == 0) {
+        LLOGE("什么情况,ptr->len == 0?!");
+        return;
+    }
     struct pbuf* p = pbuf_alloc(PBUF_TRANSPORT, ptr->len, PBUF_RAM);
     if (p == NULL) {
         LLOGD("分配pbuf失败!!! %d", ptr->len);
         luat_heap_free(ptr);
         return;
     }
+    if (p->tot_len != ptr->len) {
+        LLOGE("p->tot_len != ptr->len %d %d", p->tot_len, ptr->len);
+        return;
+    }
     pbuf_take(p, ptr->buff, ptr->len);
     // luat_airlink_hexdump("收到IP数据,注入到netif", ptr->buff, ptr->len);
     int ret = ptr->netif->input(p, ptr->netif);