fix: tcp_json_handle_sock_int RECV 被 listen socket 分支拦截导致收不到鉴权数据

- 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 处理永远不被执行
This commit is contained in:
wangfq
2026-07-01 09:20:44 +08:00
parent 19b1d7b327
commit be8c48688c

View File

@@ -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);
}
}