From be8c48688c7d7b8f3bc15b6afb619a1563cdb0de Mon Sep 17 00:00:00 2001 From: wangfq Date: Wed, 1 Jul 2026 09:20:44 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20tcp=5Fjson=5Fhandle=5Fsock=5Fint=20RECV?= =?UTF-8?q?=20=E8=A2=AB=20listen=20socket=20=E5=88=86=E6=94=AF=E6=8B=A6?= =?UTF-8?q?=E6=88=AA=E5=AF=BC=E8=87=B4=E6=94=B6=E4=B8=8D=E5=88=B0=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RECV 处理移到函数最前面,优先于 listen socket 检查 - listen socket 分支增加 socketid!=g_json_socket_client 保护, 防止 listen 与 accepted client 为同一 socket ID 时 RECV 事件被 listen 分支 return 拦截 - WCHNET 某些版本可能将 TCP_LISTEN 和已 accept 的连接 共用同一 socket ID,此时旧代码在 listen 检查处直接 return 导致后续 client RECV 处理永远不被执行 --- .../APP/tcp_json_srv.c | 91 ++++++++----------- 1 file changed, 37 insertions(+), 54 deletions(-) diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/tcp_json_srv.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/tcp_json_srv.c index 749eb4c..5bd0232 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/tcp_json_srv.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/tcp_json_srv.c @@ -85,9 +85,6 @@ static uint32_t json_get_msg_id(const char *json) { return (uint32_t)strtoul(g_tmp_value, NULL, 10); } -static void json_get_cmd(const char *json, char *out, int out_len) { - json_get_str_field(json, "\"cmd\"", out, out_len); -} static char *json_get_data_str(const char *json) { char *data = (char *)malloc(TCP_JSON_MAX_FRAME); @@ -114,6 +111,10 @@ static void json_get_str_field(const char *json, const char *key, char *out, int out[copy_len] = '\0'; } +static void json_get_cmd(const char *json, char *out, int out_len) { + json_get_str_field(json, "\"cmd\"", out, out_len); +} + static uint32_t json_get_uint_field(const char *json, const char *key) { reset_tmp(); simple_parse_json(json, key, g_tmp_value); @@ -623,75 +624,60 @@ void tcp_json_srv_init(void) { } void tcp_json_handle_sock_int(uint8_t socketid, uint8_t intstat) { - // === Listen socket events === - if (socketid == g_json_socket_listen) { + // === RECV: Always process for the client socket (handles listen==client overlap) === + if (socketid == g_json_socket_client && (intstat & SINT_STAT_RECV)) { + uint32_t recv_len = WCHNET_SocketRecvLen(socketid, NULL); + if (recv_len > 0) { + uint16_t space = TCP_JSON_RECV_BUF_LEN - g_json_recv_len; + if (recv_len > space) recv_len = space; + uint32_t rd_len = recv_len; + uint8_t tmp_buf[RECE_BUF_LEN]; + WCHNET_SocketRecv(socketid, tmp_buf, &rd_len); + memcpy(g_json_recv_buf + g_json_recv_len, tmp_buf, (uint16_t)rd_len); + g_json_recv_len += (uint16_t)rd_len; + + char frame[TCP_JSON_MAX_FRAME]; + while (json_extract_frame(g_json_recv_buf, &g_json_recv_len, frame, sizeof(frame))) { + PRINT("JSON recv: %s\n", frame); + json_process_frame(socketid, frame); + if (g_json_auth_state == JSON_STATE_WAIT_AUTH) { + g_json_auth_timer = mstick(); + } + } + if (g_json_recv_len >= TCP_JSON_MAX_FRAME) { + PRINT("JSON: frame overflow, discarding buffer\n"); + g_json_recv_len = 0; + memset(g_json_recv_buf, 0, sizeof(g_json_recv_buf)); + } + } + } + + // === Listen socket events (log only, no action needed) === + if (socketid == g_json_socket_listen && socketid != g_json_socket_client) { if (intstat & SINT_STAT_CONNECT) { - // A client connected — the accepted socket gets its own CONNECT event - // We handle the accept in the "newly accepted" path below PRINT("JSON: Listen socket got CONNECT\n"); } if (intstat & SINT_STAT_DISCONNECT) { PRINT("JSON: Listen socket disconnect (unexpected)\n"); } - return; } // === Newly accepted client (CONNECT on unknown socket) === if ((intstat & SINT_STAT_CONNECT) && socketid != g_json_socket_client && socketid != SocketId_TCP && socketid != SocketId_UDP) { - // This is the newly accepted JSON client connection g_json_socket_client = socketid; g_json_auth_state = JSON_STATE_WAIT_AUTH; g_json_pwd_retry = 0; g_json_auth_timer = mstick(); g_json_recv_len = 0; memset(g_json_recv_buf, 0, sizeof(g_json_recv_buf)); - - // CRITICAL: Set up receive buffer for the accepted TCP socket - // Use a SEPARATE buffer for WCHNET — not g_json_recv_buf - // WCHNET_SocketRecv copies FROM this buffer, so it must not overlap WCHNET_ModifyRecvBuf(socketid, (uint32_t)g_json_wchnet_buf, RECE_BUF_LEN); - PRINT("JSON: Client accepted on socket %d, recv buf configured\n", socketid); return; } - // === Client socket events === + // === Client socket events (non-RECV: CONNECT, DISCONNECT, TIMEOUT) === if (socketid == g_json_socket_client) { - if (intstat & SINT_STAT_RECV) { - // Read data from WCHNET's buffer into our frame accumulator - uint32_t recv_len = WCHNET_SocketRecvLen(socketid, NULL); - if (recv_len > 0) { - uint16_t space = TCP_JSON_RECV_BUF_LEN - g_json_recv_len; - if (recv_len > space) recv_len = space; - uint32_t rd_len = recv_len; - // Read into a temp buffer first, then append to frame buffer - uint8_t tmp_buf[RECE_BUF_LEN]; - WCHNET_SocketRecv(socketid, tmp_buf, &rd_len); - memcpy(g_json_recv_buf + g_json_recv_len, tmp_buf, (uint16_t)rd_len); - g_json_recv_len += (uint16_t)rd_len; - - // Process complete frames - char frame[TCP_JSON_MAX_FRAME]; - while (json_extract_frame(g_json_recv_buf, &g_json_recv_len, frame, sizeof(frame))) { - PRINT("JSON recv: %s\n", frame); - json_process_frame(socketid, frame); - - // Reset auth timer on activity - if (g_json_auth_state == JSON_STATE_WAIT_AUTH) { - g_json_auth_timer = mstick(); - } - } - - // Buffer overflow protection - if (g_json_recv_len >= TCP_JSON_MAX_FRAME) { - PRINT("JSON: frame overflow, discarding buffer\n"); - g_json_recv_len = 0; - memset(g_json_recv_buf, 0, sizeof(g_json_recv_buf)); - } - } - } - if (intstat & SINT_STAT_CONNECT) { PRINT("JSON: Client socket connected (id=%d)\n", socketid); g_json_auth_state = JSON_STATE_WAIT_AUTH; @@ -699,7 +685,6 @@ void tcp_json_handle_sock_int(uint8_t socketid, uint8_t intstat) { g_json_auth_timer = mstick(); g_json_recv_len = 0; } - if (intstat & SINT_STAT_DISCONNECT) { PRINT("JSON: Client disconnected (id=%d)\n", socketid); g_json_socket_client = 0xFF; @@ -707,7 +692,6 @@ void tcp_json_handle_sock_int(uint8_t socketid, uint8_t intstat) { g_json_pwd_retry = 0; g_json_recv_len = 0; } - if (intstat & SINT_STAT_TIM_OUT) { PRINT("JSON: Client timeout (id=%d)\n", socketid); g_json_socket_client = 0xFF; @@ -718,16 +702,15 @@ void tcp_json_handle_sock_int(uint8_t socketid, uint8_t intstat) { return; } - // === New socket connecting? (WCHNET assigns TCP PCB after listen accept) === + // === Fallback: connect on a socket we haven't tracked yet === if (intstat & SINT_STAT_CONNECT && g_json_socket_client == 0xFF && socketid != g_json_socket_listen) { - // This might be the newly accepted JSON client connection g_json_socket_client = socketid; g_json_auth_state = JSON_STATE_WAIT_AUTH; g_json_pwd_retry = 0; g_json_auth_timer = mstick(); g_json_recv_len = 0; memset(g_json_recv_buf, 0, sizeof(g_json_recv_buf)); - PRINT("JSON: Client accepted on socket %d\n", socketid); + PRINT("JSON: Client accepted on socket %d (fallback)\n", socketid); } }