/** ****************************************************************************** * @file tcp_server.c * @brief TCP调试服务器实现 ****************************************************************************** */ #include "tcp_server.h" #include "debug_link.h" #include "tcp_protocol.h" #include "debug_files.h" #include #include #include "publicdata/public_define.h" #include "publicdata/publicdata.h" #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include "cJSON.h" #if BLE_DEBUG_EN #include "ble_link/fc41d_ble.h" #endif #if TCP_DEBUG_EN /* TCP服务器配置 */ #define TCP_LOCAL_PORT TCP_DEBUG_PORT #define MAX_CLIENTS TCP_DEBUG_MAX_CLIENTS /* 接收数据缓冲区(用于处理多包/残包) */ #define TCP_RX_BUF_NORMAL 1024U /* 常态:心跳/参数查询等 */ #define TCP_RX_BUF_UPGRADE 8192U /* 以太网固件升级拼包 */ #define TCP_RX_BUF_UPGRADE_BLE 2048U /* BLE:单包 1024B,JSON 约 1.6KB */ typedef struct { uint8_t *buffer; uint32_t cap; uint32_t used; uint32_t processed; } tcp_rx_buffer_t; /* 服务器状态结构体实例 */ static tcp_server_state_t server_state = { .server_pcb = NULL, .client_pcb = NULL, .is_client_connected = 0, .heartbeat_sequence = 0, .system_info_sent = 0, .tick_counter = 0, .heartbeat_last_tick = 0, .system_info_last_tick = 0, .gun_data_last_tick = 0, .last_heartbeat_received_tick = 0 }; /* 接收数据缓冲区(用于多包处理) */ static tcp_rx_buffer_t rx_buffer; static SemaphoreHandle_t tcp_server_mutex = NULL; /* 服务器状态互斥锁 */ static SemaphoreHandle_t rx_buffer_mutex = NULL; /* 接收缓冲区互斥锁 */ /* 消息发送间隔(秒) */ #define HEARTBEAT_INTERVAL_SEC 10 /* 设备主动心跳(已关闭,仅保留供兼容) */ #define PERIODIC_REPORT_INTERVAL_SEC 2U /* SystemInfo + 双枪 GunInfo 周期 */ #define HEARTBEAT_TIMEOUT_SEC 30 /* 客户端心跳超时 30 秒 */ #define TCP_MSG_JSON_BUF_SIZE 768U /* GunInfo JSON 较长,预留 768 字节 */ /** 固件升级时 tcp_server_process 内追加 RX/抽帧轮次 */ #define TCP_UPGRADE_RX_BURST_PASSES 96U /* 定时判断函数 */ static uint8_t tcp_should_send_message(uint32_t last_send_tick, uint32_t interval_sec); /* 接收数据缓冲区操作函数(用于多包处理) */ static void tcp_rx_buffer_init(void); static int tcp_rx_buffer_append(const uint8_t *data, uint16_t len); static int tcp_rx_buffer_extract_json(char *output, uint32_t output_size, int *out_json_start); static void tcp_rx_buffer_rollback_to(uint32_t pos); static int s_tcp_json_is_heartbeat(const char *json); static int s_tcp_fw_data_b64_incomplete(const char *json, int json_len); static void s_tcp_log_rx_cache(const char *when); static int s_tcp_diag_rx_trace(void); static void tcp_rx_buffer_consume(uint32_t len); static void tcp_rx_buffer_reset(void); static int tcp_rx_buffer_set_cap(uint32_t cap) { uint8_t *new_buf; uint32_t keep_used; uint32_t keep_processed; if (cap == 0U) { return -1; } if ((rx_buffer.buffer != NULL) && (rx_buffer.cap == cap)) { return 0; } keep_used = rx_buffer.used; keep_processed = rx_buffer.processed; new_buf = (uint8_t *)pvPortMalloc(cap); if (new_buf == NULL) { TCP_PRINT("RX buffer alloc failed (%u bytes)\r\n", (unsigned)cap); return -1; } if ((rx_buffer.buffer != NULL) && (keep_used > 0U)) { uint32_t copy_len = keep_used; if (copy_len > cap) { copy_len = cap; keep_processed = 0U; } memcpy(new_buf, rx_buffer.buffer, copy_len); keep_used = copy_len; } if (rx_buffer.buffer != NULL) { vPortFree(rx_buffer.buffer); } rx_buffer.buffer = new_buf; rx_buffer.cap = cap; rx_buffer.used = keep_used; rx_buffer.processed = keep_processed; TCP_PRINT("RX buffer cap=%u bytes (used=%u)\r\n", (unsigned)cap, (unsigned)keep_used); return 0; } static void tcp_rx_buffer_free(void) { if (rx_buffer.buffer != NULL) { vPortFree(rx_buffer.buffer); rx_buffer.buffer = NULL; } rx_buffer.cap = 0U; rx_buffer.used = 0U; rx_buffer.processed = 0U; } int tcp_server_rx_upgrade_begin(void) { #if BLE_DEBUG_EN if (COMM_LINK_IS_BLE(comm_link_get_type())) { if (comm_link_ble_rx_upgrade_begin() != 0) { return -1; } return tcp_rx_buffer_set_cap(TCP_RX_BUF_UPGRADE_BLE); } #endif return tcp_rx_buffer_set_cap(TCP_RX_BUF_UPGRADE); } int tcp_server_rx_upgrade_end(void) { tcp_rx_buffer_reset(); #if BLE_DEBUG_EN if (COMM_LINK_IS_BLE(comm_link_get_type())) { (void)comm_link_ble_rx_upgrade_end(); } #endif return tcp_rx_buffer_set_cap(TCP_RX_BUF_NORMAL); } void tcp_server_rx_clear_pending(void) { tcp_rx_buffer_reset(); } /* 丢弃 processed 之前无 '{' 的残留字节(BLE 分片/心跳尾包) */ static int s_tcp_rx_has_partial_json(void) { int brace_count = 0; int in_string = 0; int escape_next = 0; int partial = 0; if (rx_buffer.used <= rx_buffer.processed) { return 0; } if (rx_buffer_mutex != NULL) { xSemaphoreTake(rx_buffer_mutex, portMAX_DELAY); } for (uint32_t i = rx_buffer.processed; i < rx_buffer.used; i++) { char c = rx_buffer.buffer[i]; if (escape_next) { escape_next = 0; continue; } if (c == '"' && (i == rx_buffer.processed || rx_buffer.buffer[i - 1U] != '\\')) { in_string = !in_string; continue; } if (c == '\\' && in_string) { escape_next = 1; continue; } if (!in_string) { if (c == '{') { brace_count++; } else if (c == '}') { brace_count--; } } } partial = (brace_count > 0) ? 1 : 0; if (rx_buffer_mutex != NULL) { xSemaphoreGive(rx_buffer_mutex); } return partial; } static int s_tcp_diag_rx_trace(void) { return (system_filetransfer_is_active() != 0) ? 1 : 0; } static void s_tcp_log_rx_cache_locked(const char *when) { uint32_t pending; pending = (rx_buffer.used > rx_buffer.processed) ? (rx_buffer.used - rx_buffer.processed) : 0U; tcp_firmware_upgrade_log_meta(when, rx_buffer.used, rx_buffer.processed, rx_buffer.cap, pending); if (pending > 0U) { tcp_firmware_upgrade_log_buf("TCP-CACHE-DATA", (const uint8_t *)(rx_buffer.buffer + rx_buffer.processed), pending); } } static void s_tcp_log_rx_cache(const char *when) { if (s_tcp_diag_rx_trace() == 0) { return; } if (rx_buffer_mutex != NULL) { xSemaphoreTake(rx_buffer_mutex, portMAX_DELAY); } s_tcp_log_rx_cache_locked(when); if (rx_buffer_mutex != NULL) { xSemaphoreGive(rx_buffer_mutex); } } static void tcp_rx_buffer_skip_leading_garbage(void) { uint32_t i; int first_brace = -1; if (rx_buffer.used <= rx_buffer.processed) { return; } if (rx_buffer_mutex != NULL) { xSemaphoreTake(rx_buffer_mutex, portMAX_DELAY); } for (i = rx_buffer.processed; i < rx_buffer.used; i++) { if (rx_buffer.buffer[i] == '{') { first_brace = (int)i; break; } } if (first_brace > (int)rx_buffer.processed) { TCP_PRINT("Skip %u bytes before JSON '{'\r\n", (unsigned)((uint32_t)first_brace - rx_buffer.processed)); rx_buffer.processed = (uint32_t)first_brace; } if (rx_buffer_mutex != NULL) { xSemaphoreGive(rx_buffer_mutex); } } /* 接收缓冲区处理函数 */ static void tcp_server_process_rx_buffer(void); /* Socket API相关函数 */ static int tcp_server_socket_receive_data(void) { uint8_t temp_buffer[1024]; int received = 0; int total = 0; int link_error = 0; for (;;) { received = comm_link_receive_data(temp_buffer, sizeof(temp_buffer)); if (received < 0) { link_error = received; break; } if (received == 0) { break; } if (tcp_rx_buffer_append(temp_buffer, (uint16_t)received) != 0) { TCP_PRINT("Failed to append data to RX buffer from socket\r\n"); } else { if (s_tcp_diag_rx_trace() != 0) { if (system_filetransfer_is_active() != 0) { system_filetransfer_touch_activity_on_rx(); } tcp_firmware_upgrade_log_io("RX-LINK", (const char *)temp_buffer, (uint32_t)received); } TCP_PRINT("Added %d bytes to RX buffer from socket\r\n", received); } total += received; if (s_tcp_diag_rx_trace() == 0) { break; } } if (link_error < 0) { TCP_PRINT("Socket receive error or connection closed: %d\r\n", link_error); if (tcp_server_mutex != NULL) { xSemaphoreTake(tcp_server_mutex, portMAX_DELAY); } server_state.is_client_connected = 0; if (tcp_server_mutex != NULL) { xSemaphoreGive(tcp_server_mutex); } tcp_rx_buffer_reset(); return link_error; } return total; } void upgrade_erase_yield(void) { #if BLE_DEBUG_EN if (COMM_LINK_IS_BLE(comm_link_get_type())) { comm_link_ble_process(); } #endif if (server_state.is_client_connected) { uint8_t pass; for (pass = 0U; pass < 4U; pass++) { if (tcp_server_socket_receive_data() <= 0) { break; } } } } void tcp_server_link_rx_drain(void) { uint8_t pass; if (!server_state.is_client_connected) { return; } for (pass = 0U; pass < 32U; pass++) { int got = tcp_server_socket_receive_data(); if (got <= 0) { break; } } } /** * @brief 发送数据到客户端(Socket API版本) * @param data 要发送的数据 * @param len 数据长度 * @retval 发送的字节数,-1表示错误 */ static int tcp_server_send_data_socket(const void *data, uint16_t len) { if (data == NULL || len == 0) { return -1; } #if TCP_DEBUG_EN if (s_tcp_diag_rx_trace() != 0) { tcp_firmware_upgrade_log_io("TX-LINK", (const char *)data, (uint32_t)len); } #endif /* 打印原始发送数据 */ TCP_PRINT_RAW_SEND((const uint8_t *)data, len); /* 使用Socket API发送数据 */ return comm_link_send_data((const uint8_t *)data, len); } /** * @brief 判断是否应该发送消息(基于时间间隔) * @param last_send_tick 上次发送时的tick * @param interval_sec 发送间隔(秒) * @retval 1应该发送,0不应该发送 */ static uint8_t tcp_should_send_message(uint32_t last_send_tick, uint32_t interval_sec) { uint32_t elapsed = server_state.tick_counter - last_send_tick; return (elapsed >= interval_sec) ? 1 : 0; } /** * @brief 初始化接收数据缓冲区 */ static void tcp_rx_buffer_init(void) { rx_buffer_mutex = xSemaphoreCreateMutex(); if (rx_buffer_mutex == NULL) { TCP_PRINT("Failed to create RX buffer mutex\r\n"); return; } rx_buffer.buffer = NULL; rx_buffer.cap = 0U; rx_buffer.used = 0U; rx_buffer.processed = 0U; if (tcp_rx_buffer_set_cap(TCP_RX_BUF_NORMAL) != 0) { TCP_PRINT("RX buffer normal alloc failed\r\n"); } } /** * @brief 重置接收数据缓冲区 */ static void tcp_rx_buffer_reset(void) { /* 获取接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreTake(rx_buffer_mutex, portMAX_DELAY); } rx_buffer.used = 0; rx_buffer.processed = 0; /* 释放接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreGive(rx_buffer_mutex); } } /** * @brief 将数据追加到接收缓冲区 * @param data 数据指针 * @param len 数据长度 * @retval 0成功,-1失败(缓冲区满) */ static int tcp_rx_buffer_append(const uint8_t *data, uint16_t len) { int result = -1; if (data == NULL || len == 0) { return -1; } /* 获取接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreTake(rx_buffer_mutex, portMAX_DELAY); } /* 检查缓冲区是否有足够空间 */ if (rx_buffer.buffer == NULL || rx_buffer.cap == 0U) { result = -1; } else if (rx_buffer.used + len > rx_buffer.cap) { TCP_PRINT("RX buffer full! Used: %u, Adding: %u, Max: %u\r\n", rx_buffer.used, len, rx_buffer.cap); result = -1; } else { #if TCP_DEBUG_EN if (s_tcp_diag_rx_trace() != 0) { if ((len >= 12U) && (data[0] == (uint8_t)'{')) { uint16_t peek = (len > 128U) ? 128U : len; char head[129]; memcpy(head, data, peek); head[peek] = '\0'; if ((strstr(head, CMD_FIRMWARE_UPGRADE) != NULL) && (s_tcp_rx_has_partial_json() != 0)) { TCP_PRINT("Upgrade host retry: drop partial JSON (%u bytes)\r\n", (unsigned)(rx_buffer.used - rx_buffer.processed)); rx_buffer.used = rx_buffer.processed; } } } #endif /* 复制数据到缓冲区 */ memcpy(rx_buffer.buffer + rx_buffer.used, data, len); rx_buffer.used += len; TCP_PRINT("Added %u bytes to RX buffer, total: %u\r\n", len, rx_buffer.used); result = 0; #if TCP_DEBUG_EN if (s_tcp_diag_rx_trace() != 0) { s_tcp_log_rx_cache_locked("TCP-after-append"); } #endif } /* 释放接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreGive(rx_buffer_mutex); } return result; } /** * @brief 从缓冲区提取完整的JSON消息 * @param output 输出缓冲区 * @param output_size 输出缓冲区大小 * @param out_json_start 可选,返回本条 JSON 在缓冲中的起始下标(用于半包回退) * @retval JSON消息长度,0表示没有完整消息,-1表示错误 */ static int tcp_rx_buffer_extract_json(char *output, uint32_t output_size, int *out_json_start) { int brace_count = 0; int json_start = -1; int json_end = -1; int in_string = 0; int escape_next = 0; int i; int result = 0; if (output == NULL || output_size == 0) { return -1; } /* 获取接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreTake(rx_buffer_mutex, portMAX_DELAY); } /* 查找完整的JSON消息(通过括号匹配,忽略字符串内的括号) */ for (i = rx_buffer.processed; i < rx_buffer.used; i++) { char c = rx_buffer.buffer[i]; /* 处理转义字符 */ if (escape_next) { escape_next = 0; continue; } /* 处理字符串开始/结束 */ if (c == '"' && (i == rx_buffer.processed || rx_buffer.buffer[i-1] != '\\')) { in_string = !in_string; continue; } /* 处理转义字符标记 */ if (c == '\\' && in_string) { escape_next = 1; continue; } /* 只有在不在字符串内时才计数括号 */ if (!in_string) { if (c == '{') { if (brace_count == 0) { json_start = i; /* 记录JSON开始位置 */ } brace_count++; } else if (c == '}') { brace_count--; if (brace_count == 0 && json_start != -1) { json_end = i; /* 记录JSON结束位置 */ break; } else if (brace_count < 0) { /* 括号不匹配,重置状态 */ brace_count = 0; json_start = -1; } } } } /* 检查是否找到完整的JSON消息 */ if (json_start != -1 && json_end != -1) { int json_len = json_end - json_start + 1; /* 检查输出缓冲区是否足够 */ if (json_len >= output_size) { TCP_PRINT("JSON too large for output buffer: %d >= %u\r\n", json_len, output_size); result = -1; } else { /* 复制JSON消息到输出缓冲区 */ memcpy(output, rx_buffer.buffer + json_start, json_len); output[json_len] = '\0'; if (out_json_start != NULL) { *out_json_start = json_start; } /* 更新已处理位置 */ rx_buffer.processed = (uint32_t)(json_end + 1); TCP_PRINT("Extracted JSON message (%d bytes)\r\n", json_len); result = json_len; } } else { /* 没有找到完整的JSON消息 */ if (rx_buffer.used - rx_buffer.processed > 0) { TCP_PRINT("No complete JSON found. Buffer: remaining=%u bytes\r\n", rx_buffer.used - rx_buffer.processed); /* 调试:打印缓冲区的前200个字符 */ uint32_t remaining = rx_buffer.used - rx_buffer.processed; if (remaining > 0) { char debug_buf[256]; uint32_t copy_len = (remaining < 200) ? remaining : 200; memcpy(debug_buf, rx_buffer.buffer + rx_buffer.processed, copy_len); debug_buf[copy_len] = '\0'; TCP_PRINT("Buffer content (first %u bytes): %s\r\n", copy_len, debug_buf); } /* 检查是否有可能是JSON消息的一部分(但没有开头的'{') */ /* 这种情况可能发生在JSON消息被TCP分割时 */ if (json_start == -1 && json_end == -1) { /* 检查缓冲区中是否有JSON格式的字符 */ int has_json_chars = 0; for (uint32_t j = rx_buffer.processed; j < rx_buffer.used; j++) { char c = rx_buffer.buffer[j]; if (c == '"' || c == ':' || c == ',' || c == '[' || c == ']' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '.' || c == '-' || c == '+' || c == '=') { has_json_chars = 1; break; } } if (has_json_chars) { TCP_PRINT("Buffer contains JSON-like data but no complete JSON message found\r\n"); TCP_PRINT("This may be a partial JSON message (split by TCP)\r\n"); } } } result = 0; } /* 释放接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreGive(rx_buffer_mutex); } return result; } static void tcp_rx_buffer_rollback_to(uint32_t pos) { if (rx_buffer_mutex != NULL) { xSemaphoreTake(rx_buffer_mutex, portMAX_DELAY); } if (pos <= rx_buffer.used) { rx_buffer.processed = pos; } if (rx_buffer_mutex != NULL) { xSemaphoreGive(rx_buffer_mutex); } } static int s_tcp_json_is_heartbeat(const char *json) { if (json == NULL) { return 0; } return (strstr(json, "\"command\":\"Heartbeat\"") != NULL) ? 1 : 0; } static int s_tcp_fw_data_b64_incomplete(const char *json, int json_len) { const char *subcmd; const char *p; const char *end; const char *pi; uint32_t b64_len; uint32_t pkt = 0U; uint32_t expect = 0U; uint32_t min_b64; const char *b64_field = NULL; if ((json == NULL) || (json_len <= 0)) { return 0; } if (strstr(json, CMD_FIRMWARE_UPGRADE) == NULL) { return 0; } subcmd = strstr(json, "\"subCommand\":\"Data\""); if (subcmd == NULL) { subcmd = strstr(json, "\"subCommand\": \"Data\""); } if (subcmd == NULL) { return 0; } /* 在 data 对象内查找值为字符串的 "data" 字段(Base64 载荷,非外层 "data":{) */ p = json; while ((p = strstr(p, "\"data\"")) != NULL) { const char *col; p += 6; col = strchr(p, ':'); if (col == NULL) { break; } col++; while ((col < json + json_len) && (*col == ' ' || *col == '\t')) { col++; } if (*col == '"') { b64_field = col + 1; break; } } if (b64_field == NULL) { return 1; } p = b64_field; end = p; while (end < json + json_len) { if (*end == '"') { break; } if ((*end == '\\') && (end + 1 < json + json_len)) { end += 2; } else { end++; } } if (*end != '"') { return 1; } b64_len = (uint32_t)(end - p); pi = strstr(json, "\"packetIndex\""); if (pi != NULL) { (void)sscanf(pi, "\"packetIndex\":%u", &pkt); } if (system_filetransfer_get_expected_packet_bytes(pkt, &expect) != 0 || expect == 0U) { return 0; } min_b64 = ((expect + 2U) / 3U) * 4U; return (b64_len < min_b64) ? 1 : 0; } /** * @brief 消费已处理的数据(移动未处理数据到缓冲区开头) * @param len 要消费的长度 */ static void tcp_rx_buffer_consume(uint32_t len) { if (len == 0 || len > rx_buffer.processed) { return; } /* 获取接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreTake(rx_buffer_mutex, portMAX_DELAY); } /* 移动未处理数据到缓冲区开头 */ uint32_t remaining = rx_buffer.used - rx_buffer.processed; if (remaining > 0) { memmove(rx_buffer.buffer, rx_buffer.buffer + rx_buffer.processed, remaining); } /* 更新缓冲区状态 */ rx_buffer.used = remaining; rx_buffer.processed = 0; TCP_PRINT("Consumed %u bytes from RX buffer, remaining: %u\r\n", len, rx_buffer.used); /* 如果缓冲区为空,重置状态 */ if (rx_buffer.used == 0) { TCP_PRINT("RX buffer is empty, ready for new data\r\n"); } /* 释放接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreGive(rx_buffer_mutex); } } /** * @brief 启动TCP服务器(Socket API版本) * @retval err_t 错误码 */ err_t tcp_server_start(void) { int result; cJSON_Hooks hooks; /* 初始化cJSON使用FreeRTOS内存分配器 */ hooks.malloc_fn = pvPortMalloc; hooks.free_fn = vPortFree; cJSON_InitHooks(&hooks); /* 创建服务器状态互斥锁 */ tcp_server_mutex = xSemaphoreCreateMutex(); if (tcp_server_mutex == NULL) { TCP_PRINT("Failed to create server mutex\r\n"); return ERR_MEM; } /* 初始化接收缓冲区(内部会创建接收缓冲区互斥锁) */ tcp_rx_buffer_init(); system_filetransfer_init(); /* 检查接收缓冲区互斥锁是否创建成功 */ if (rx_buffer_mutex == NULL) { TCP_PRINT("Failed to create RX buffer mutex\r\n"); vSemaphoreDelete(tcp_server_mutex); tcp_server_mutex = NULL; return ERR_MEM; } /* 使用Socket API初始化TCP服务器 */ result = comm_link_start(); if (result != 0) { TCP_PRINT("Failed to initialize socket server: %d\r\n", result); vSemaphoreDelete(rx_buffer_mutex); rx_buffer_mutex = NULL; vSemaphoreDelete(tcp_server_mutex); tcp_server_mutex = NULL; return ERR_MEM; } /* 获取互斥锁保护状态变量 */ if (tcp_server_mutex != NULL) { xSemaphoreTake(tcp_server_mutex, portMAX_DELAY); } /* 重置服务器状态 */ server_state.system_info_sent = 0; server_state.heartbeat_last_tick = 0; server_state.system_info_last_tick = 0; server_state.gun_data_last_tick = 0; server_state.last_heartbeat_received_tick = 0; server_state.heartbeat_sequence = 0; server_state.is_client_connected = 0; server_state.client_pcb = NULL; server_state.server_pcb = NULL; /* 释放互斥锁 */ if (tcp_server_mutex != NULL) { xSemaphoreGive(tcp_server_mutex); } if (comm_link_get_type() == COMM_LINK_TCP) { TCP_PRINT("Debug server started, link=TCP port=%d\r\n", TCP_LOCAL_PORT); } else { TCP_PRINT("Debug server started, link=BLE (FC41D)\r\n"); } return ERR_OK; } /** * @brief 停止TCP服务器 */ void tcp_server_stop(void) { /* 获取互斥锁保护状态变量 */ if (tcp_server_mutex != NULL) { xSemaphoreTake(tcp_server_mutex, portMAX_DELAY); } /* 关闭客户端连接(使用Socket API) */ comm_link_close_client(); comm_link_stop(); /* 重置协议相关状态 */ server_state.system_info_sent = 0; server_state.heartbeat_last_tick = 0; server_state.system_info_last_tick = 0; server_state.gun_data_last_tick = 0; server_state.last_heartbeat_received_tick = 0; server_state.heartbeat_sequence = 0; server_state.is_client_connected = 0; server_state.client_pcb = NULL; server_state.server_pcb = NULL; /* 释放互斥锁 */ if (tcp_server_mutex != NULL) { xSemaphoreGive(tcp_server_mutex); } /* 删除服务器状态互斥锁 */ if (tcp_server_mutex != NULL) { vSemaphoreDelete(tcp_server_mutex); tcp_server_mutex = NULL; } /* 删除接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { vSemaphoreDelete(rx_buffer_mutex); rx_buffer_mutex = NULL; } /* 重置接收缓冲区 */ tcp_rx_buffer_reset(); TCP_PRINT("Server stopped (Socket API)\r\n"); } /** * @brief 发送指定类型的消息给客户端(Socket API版本) * @param msg_type 消息类型(TCP_MSG_HEARTBEAT或TCP_MSG_SYSTEM_INFO) */ void tcp_server_send_message(tcp_msg_type_t msg_type) { char json_buffer[TCP_MSG_JSON_BUF_SIZE]; int json_len; int sent; if (system_filetransfer_is_active() != 0) { return; } /* 检查客户端是否连接(使用Socket API) */ if (!comm_link_is_client_connected()) { return; } switch (msg_type) { case TCP_MSG_HEARTBEAT: { /* 生成心跳JSON */ json_len = tcp_generate_heartbeat_json(server_state.heartbeat_sequence, "device", json_buffer, sizeof(json_buffer)); if (json_len <= 0) { TCP_PRINT("Failed to generate heartbeat JSON\r\n"); return; } /* 发送JSON数据(使用Socket API) */ sent = tcp_server_send_data_socket(json_buffer, json_len); if (sent > 0) { server_state.heartbeat_sequence++; /* 序列号递增 */ TCP_PRINT("Sent heartbeat (seq=%u)\r\n", server_state.heartbeat_sequence - 1); } else { TCP_PRINT("Failed to send heartbeat: %d\r\n", sent); } break; } case TCP_MSG_SYSTEM_INFO: { tcp_system_info_data_t system_info; /* 获取默认系统信息 */ tcp_get_default_system_info(&system_info); /* 生成系统信息JSON */ json_len = tcp_generate_system_info_json(&system_info, json_buffer, sizeof(json_buffer)); if (json_len <= 0) { TCP_PRINT("Failed to generate system info JSON\r\n"); return; } /* 发送JSON数据(使用Socket API) */ sent = tcp_server_send_data_socket(json_buffer, json_len); if (sent > 0) { TCP_PRINT("Sent system info\r\n"); } else { TCP_PRINT("Failed to send system info: %d\r\n", sent); } break; } case TCP_MSG_GUN_DATA: { /* 发送各枪实时数据 */ for (uint8_t gun_num = 1; gun_num <= (uint8_t)GUN_MAX_CNT; gun_num++) { tcp_gun_data_t gun_data; tcp_get_default_gun_data(&gun_data, gun_num); json_len = tcp_generate_gun_data_json(&gun_data, json_buffer, sizeof(json_buffer)); if (json_len <= 0) { TCP_PRINT("Failed to generate gun data JSON for gun %u\r\n", (unsigned)gun_num); #if BLE_DEBUG_EN BT_PRINT("GunInfo JSON fail gun=%u\r\n", (unsigned)gun_num); #endif continue; } sent = tcp_server_send_data_socket(json_buffer, (uint16_t)json_len); if (sent > 0) { TCP_PRINT("Sent gun data for gun %u\r\n", (unsigned)gun_num); } else { TCP_PRINT("Failed to send gun data for gun %u: %d\r\n", (unsigned)gun_num, sent); #if BLE_DEBUG_EN BT_PRINT("GunInfo send fail gun=%u ret=%d\r\n", (unsigned)gun_num, sent); #endif } #if BLE_DEBUG_EN if (COMM_LINK_IS_BLE(comm_link_get_type())) { vTaskDelay(pdMS_TO_TICKS(80)); } else #endif { vTaskDelay(pdMS_TO_TICKS(10)); } } break; } default: TCP_PRINT("Unknown message type: %d\r\n", msg_type); break; } } /** * @brief 发送JSON数据给客户端(Socket API版本) * @param json_data JSON字符串 * @param len 数据长度 * @retval err_t 错误码 */ err_t tcp_server_send_json(const char *json_data, uint16_t len) { int sent; if (json_data == NULL || len == 0) { return ERR_ARG; } /* 检查客户端是否连接(使用Socket API) */ if (!comm_link_is_client_connected()) { TCP_PRINT("Cannot send JSON: no client connected\r\n"); return ERR_CONN; } /* 发送JSON数据(使用Socket API) */ sent = tcp_server_send_data_socket(json_data, len); if (sent > 0) { #if BLE_DEBUG_EN if (!COMM_LINK_IS_BLE(comm_link_get_type())) { (void)tcp_server_send_data_socket("\r\n", 2); TCP_PRINT("Sent JSON data (%u bytes) + CRLF\r\n", len); } else { TCP_PRINT("Sent JSON data (%u bytes)\r\n", len); } #else (void)tcp_server_send_data_socket("\r\n", 2); TCP_PRINT("Sent JSON data (%u bytes) + CRLF\r\n", len); #endif return ERR_OK; } else { TCP_PRINT("Failed to send JSON data: %d\r\n", sent); return ERR_IF; } } /** * @brief 处理接收缓冲区中的数据(提取并处理完整的JSON消息) */ static void tcp_server_process_rx_buffer(void) { char *json_buffer = NULL; /* 动态分配缓冲区以处理JSON消息 */ int json_len; int processed_any = 0; int has_partial_json = 0; /* 动态分配JSON缓冲区 */ json_buffer = (char *)pvPortMalloc(rx_buffer.cap > 0U ? rx_buffer.cap : TCP_RX_BUF_NORMAL); if (json_buffer == NULL) { TCP_PRINT("Failed to allocate JSON buffer (%u bytes)\r\n", (unsigned)(rx_buffer.cap > 0U ? rx_buffer.cap : TCP_RX_BUF_NORMAL)); return; } /* 检查是否有部分JSON消息(有'{'但没有匹配的'}',或者有'}'但没有匹配的'{') */ if (rx_buffer.used > rx_buffer.processed) { int brace_count = 0; int in_string = 0; int escape_next = 0; int has_open_brace = 0; int has_close_brace = 0; for (uint32_t i = rx_buffer.processed; i < rx_buffer.used; i++) { char c = rx_buffer.buffer[i]; /* 处理转义字符 */ if (escape_next) { escape_next = 0; continue; } /* 处理字符串开始/结束 */ if (c == '"' && (i == rx_buffer.processed || rx_buffer.buffer[i-1] != '\\')) { in_string = !in_string; continue; } /* 处理转义字符标记 */ if (c == '\\' && in_string) { escape_next = 1; continue; } /* 只有在不在字符串内时才计数括号 */ if (!in_string) { if (c == '{') { brace_count++; has_open_brace = 1; } else if (c == '}') { brace_count--; has_close_brace = 1; } } } /* 如果有未匹配的'{',说明有部分JSON消息(等待更多数据) */ if (brace_count > 0) { has_partial_json = 1; TCP_PRINT("Partial JSON detected in buffer (unmatched braces: %d)\r\n", brace_count); } /* 如果只有'}'没有'{',可能是JSON消息被分割,开头部分在之前的数据包中 */ else if (has_close_brace && !has_open_brace) { has_partial_json = 1; TCP_PRINT("Partial JSON detected (only close brace found, waiting for more data)\r\n"); } /* 如果缓冲区中有数据但没有括号,可能是JSON消息的一部分(如字符串中间) */ else if (rx_buffer.used - rx_buffer.processed > 0 && !has_open_brace && !has_close_brace) { /* 检查缓冲区中是否有JSON格式的字符(如引号、冒号等) */ int has_json_chars = 0; for (uint32_t i = rx_buffer.processed; i < rx_buffer.used; i++) { char c = rx_buffer.buffer[i]; if (c == '"' || c == ':' || c == ',' || c == '[' || c == ']') { has_json_chars = 1; break; } } if (has_json_chars) { has_partial_json = 1; TCP_PRINT("Partial JSON detected (JSON characters found, waiting for more data)\r\n"); } } } /* 循环提取并处理所有完整的JSON消息 */ while (1) { int json_start_pos = -1; json_len = tcp_rx_buffer_extract_json(json_buffer, rx_buffer.cap > 0U ? rx_buffer.cap : TCP_RX_BUF_NORMAL, &json_start_pos); if (json_len > 0) { if (system_filetransfer_is_active() != 0) { if (s_tcp_json_is_heartbeat(json_buffer) != 0) { processed_any = 1; continue; } if (s_tcp_fw_data_b64_incomplete(json_buffer, json_len) != 0) { TCP_PRINT("Upgrade JSON incomplete b64, rollback\r\n"); s_tcp_log_rx_cache("TCP-b64-incomplete"); if (json_start_pos >= 0) { tcp_rx_buffer_rollback_to((uint32_t)json_start_pos); } break; } } tcp_server_process_received_data(json_buffer, (uint16_t)json_len); processed_any = 1; #if TCP_DEBUG_EN if (s_tcp_diag_rx_trace() != 0) { s_tcp_log_rx_cache("TCP-after-json-ok"); } #endif } else if (json_len == 0) { /* 没有完整的JSON消息 */ #if TCP_DEBUG_EN if (s_tcp_diag_rx_trace() != 0) { s_tcp_log_rx_cache("TCP-no-full-json"); } #endif break; } else { /* 错误 */ TCP_PRINT("Failed to extract JSON from RX buffer\r\n"); break; } } /* 消费已处理的数据 */ if (rx_buffer.processed > 0) { tcp_rx_buffer_consume(rx_buffer.processed); #if TCP_DEBUG_EN if (s_tcp_diag_rx_trace() != 0) { s_tcp_log_rx_cache("TCP-after-consume"); } #endif } else if (rx_buffer.used > 0) { /* 如果没有找到完整的JSON消息,但缓冲区中有数据 */ /* 检查缓冲区使用率是否过高 */ uint8_t buffer_usage_high = (rx_buffer.cap > 0U) && (rx_buffer.used > (rx_buffer.cap * 3U / 4U)); if (buffer_usage_high) { /* 固件升级中保留半包 JSON,禁止丢弃(避免 Base64 被截断) */ if (system_filetransfer_is_active() != 0) { TCP_PRINT("RX buffer high (%u/%u) during upgrade, keep partial JSON\r\n", rx_buffer.used, rx_buffer.cap); } else if (has_partial_json) { /* 有部分JSON消息,但缓冲区快满了 */ /* 尝试查找缓冲区中是否有'{'字符,从那里开始保留数据 */ int first_brace_pos = -1; /* 获取接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreTake(rx_buffer_mutex, portMAX_DELAY); } /* 查找第一个'{'字符 */ for (uint32_t i = 0; i < rx_buffer.used; i++) { if (rx_buffer.buffer[i] == '{') { first_brace_pos = i; break; } } if (first_brace_pos > 0) { /* 找到'{'字符,清理之前的数据 */ TCP_PRINT("RX buffer high (%u/%u) with partial JSON, cleaning %u bytes before first '{'\r\n", rx_buffer.used, rx_buffer.cap, first_brace_pos); tcp_rx_buffer_consume(first_brace_pos); } else if (first_brace_pos == -1) { /* 没有找到'{'字符,清理一半的数据 */ TCP_PRINT("RX buffer high (%u/%u) with partial JSON but no '{', cleaning half of data\r\n", rx_buffer.used, rx_buffer.cap); uint32_t clean_len = rx_buffer.used / 2; if (clean_len > 0) { tcp_rx_buffer_consume(clean_len); } } /* 释放接收缓冲区互斥锁 */ if (rx_buffer_mutex != NULL) { xSemaphoreGive(rx_buffer_mutex); } } else { /* 没有部分JSON消息,清理一半的数据 */ TCP_PRINT("RX buffer usage high (%u/%u), no partial JSON, cleaning half of data\r\n", rx_buffer.used, rx_buffer.cap); uint32_t clean_len = rx_buffer.used / 2; if (clean_len > 0) { tcp_rx_buffer_consume(clean_len); } } } } if (json_buffer != NULL) { vPortFree(json_buffer); json_buffer = NULL; } } /** * @brief 处理接收到的数据 */ void tcp_server_process_received_data(const char *data, uint16_t len) { tcp_message_t message; //printf("tcp_message_t size is %d\r\n",sizeof(tcp_message_t)); if (data == NULL || len == 0) { return; } /* 尝试解析JSON消息 */ if (tcp_parse_json_message(data, &message) == 0) { #if TCP_DEBUG_EN if (strcmp(message.command, CMD_FIRMWARE_UPGRADE) == 0) { tcp_firmware_upgrade_log_io("RX", (const char *)data, (uint32_t)len); } if (system_filetransfer_is_active() != 0) { if (strcmp(message.command, CMD_HEARTBEAT) == 0) { tcp_free_message(&message); return; } if (strcmp(message.command, CMD_FIRMWARE_UPGRADE) != 0) { TCP_PRINT("Drop command '%s' during firmware upgrade\r\n", message.command); tcp_free_message(&message); return; } } #endif /* 解析成功,处理消息 */ tcp_process_received_message(&message); /* 释放消息中动态分配的内存 */ tcp_free_message(&message); /* 如果是心跳消息,更新最后收到心跳的时间 */ if (strcmp(message.command, CMD_HEARTBEAT) == 0) { /* 获取互斥锁保护状态变量 */ if (tcp_server_mutex != NULL) { xSemaphoreTake(tcp_server_mutex, portMAX_DELAY); } server_state.last_heartbeat_received_tick = server_state.tick_counter; TCP_PRINT("Heartbeat received, updated last tick to %u\r\n", server_state.tick_counter); /* 释放互斥锁 */ if (tcp_server_mutex != NULL) { xSemaphoreGive(tcp_server_mutex); } } } else { /* 如果不是有效的JSON,打印原始数据 */ TCP_PRINT("Received raw data (%d bytes): %s\r\n", len, data); } } static void tcp_server_send_ctrl(void) { uint8_t due = 0U; if (system_filetransfer_is_active() != 0) { return; } if (tcp_server_mutex != NULL) { xSemaphoreTake(tcp_server_mutex, portMAX_DELAY); } if (server_state.is_client_connected) { if (server_state.system_info_sent == 0U) { due = 1U; } else if (tcp_should_send_message(server_state.system_info_last_tick, PERIODIC_REPORT_INTERVAL_SEC)) { due = 1U; } if (due != 0U) { server_state.system_info_sent = 1U; server_state.system_info_last_tick = server_state.tick_counter; server_state.gun_data_last_tick = server_state.tick_counter; } } if (tcp_server_mutex != NULL) { xSemaphoreGive(tcp_server_mutex); } if (due == 0U) { return; } #if BLE_DEBUG_EN if (COMM_LINK_IS_BLE(comm_link_get_type())) { BT_PRINT("tcp_server: send SystemInfo+GunInfo\r\n"); } #endif tcp_server_send_message(TCP_MSG_SYSTEM_INFO); #if BLE_DEBUG_EN if (COMM_LINK_IS_BLE(comm_link_get_type())) { vTaskDelay(pdMS_TO_TICKS(120)); } else #endif { vTaskDelay(pdMS_TO_TICKS(20)); } tcp_server_send_message(TCP_MSG_GUN_DATA); } /** * @brief TCP服务器处理函数(周期性调用)- Socket API版本 */ void tcp_server_process(void) { uint8_t should_check_heartbeat_timeout = 0; static U32_T tick_counter = 0; U32_T tick_counter_now = get_current_seconds(); comm_link_process(); /* 更新tick计数器 */ if (tcp_server_mutex != NULL) { xSemaphoreTake(tcp_server_mutex, portMAX_DELAY); } if(tick_counter_now != tick_counter) { server_state.tick_counter++; tick_counter = tick_counter_now; } /* 检查客户端连接状态(使用Socket API) */ int is_connected = comm_link_is_client_connected(); /* 更新服务器状态中的连接状态 */ if (server_state.is_client_connected != is_connected) { server_state.is_client_connected = is_connected; if (is_connected) { /* 新客户端连接 */ server_state.system_info_sent = 0; /* 连接成功后需要第一时间发送系统信息 */ server_state.heartbeat_last_tick = 0; server_state.system_info_last_tick = 0; server_state.gun_data_last_tick = 0; server_state.last_heartbeat_received_tick = 0; TCP_PRINT("Client connected (Socket API)\r\n"); #if BLE_DEBUG_EN if (COMM_LINK_IS_BLE(comm_link_get_type())) { BT_PRINT("tcp_server: BLE client up, begin RX/TX\r\n"); } #endif } else { /* 客户端断开连接 */ TCP_PRINT("Client disconnected (Socket API)\r\n"); /* 重置接收缓冲区 */ tcp_rx_buffer_reset(); } } /* 检查是否需要发送心跳 */ if (server_state.is_client_connected) { /* 检查心跳超时(仅在收到过心跳后才检查) */ if (server_state.last_heartbeat_received_tick > 0) { uint32_t heartbeat_timeout_elapsed = server_state.tick_counter - server_state.last_heartbeat_received_tick; if (heartbeat_timeout_elapsed >= HEARTBEAT_TIMEOUT_SEC) { should_check_heartbeat_timeout = 1; TCP_PRINT("Heartbeat timeout detected! Elapsed: %u seconds\r\n", heartbeat_timeout_elapsed); } } } /* 释放互斥锁 */ if (tcp_server_mutex != NULL) { xSemaphoreGive(tcp_server_mutex); } /* Socket API处理逻辑 */ /* 1. 接受新的客户端连接 */ if (!server_state.is_client_connected) { int accept_result = comm_link_accept_client(); if (accept_result > 0) { /* 新客户端连接成功 */ if (tcp_server_mutex != NULL) { xSemaphoreTake(tcp_server_mutex, portMAX_DELAY); } server_state.is_client_connected = 1; server_state.system_info_sent = 0; server_state.heartbeat_last_tick = 0; server_state.system_info_last_tick = 0; server_state.gun_data_last_tick = 0; server_state.last_heartbeat_received_tick = 0; if (tcp_server_mutex != NULL) { xSemaphoreGive(tcp_server_mutex); } } } /* 2. 接收数据(如果有客户端连接) */ if (server_state.is_client_connected) { tcp_server_socket_receive_data(); } /* 3. 处理接收缓冲区 */ if (system_filetransfer_is_active() != 0) { tcp_rx_buffer_skip_leading_garbage(); } tcp_server_process_rx_buffer(); if (system_filetransfer_is_active() != 0) { uint8_t pass; for (pass = 0U; pass < TCP_UPGRADE_RX_BURST_PASSES; pass++) { comm_link_process(); (void)tcp_server_socket_receive_data(); tcp_server_process_rx_buffer(); } } /* 4. 处理心跳超时(固件升级期间不判心跳超时) */ system_filetransfer_poll_idle_timeout(); if (system_filetransfer_is_active() != 0) { should_check_heartbeat_timeout = 0U; } if (should_check_heartbeat_timeout) { TCP_PRINT("Disconnecting client due to heartbeat timeout\r\n"); /* 关闭客户端连接 */ comm_link_close_client(); /* 获取互斥锁保护状态变量 */ if (tcp_server_mutex != NULL) { xSemaphoreTake(tcp_server_mutex, portMAX_DELAY); } server_state.is_client_connected = 0; /* 释放互斥锁 */ if (tcp_server_mutex != NULL) { xSemaphoreGive(tcp_server_mutex); } /* 重置接收缓冲区 */ tcp_rx_buffer_reset(); } /* 5. 发送控制消息(心跳、系统信息等) */ tcp_server_send_ctrl(); } #else /* TCP_DEBUG_EN */ /* 当TCP_DEBUG_EN未使能时,提供空实现以避免链接错误 */ err_t tcp_server_start(void) { return ERR_OK; } void tcp_server_stop(void) { } void tcp_server_process(void) { } void tcp_server_send_heartbeat(void) { } void tcp_server_send_system_info(void) { } err_t tcp_server_send_json(const char *json_data, uint16_t len) { LWIP_UNUSED_ARG(json_data); LWIP_UNUSED_ARG(len); return ERR_OK; } void tcp_server_process_received_data(const char *data, uint16_t len) { LWIP_UNUSED_ARG(data); LWIP_UNUSED_ARG(len); } void tcp_server_task(void *arg) { LWIP_UNUSED_ARG(arg); } void tcp_server_process(void) { /* CCU621_M compat stub */ } #endif /* TCP_DEBUG_EN */