From 756c9919f95b4d039fb422df18152907a7bbca01 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=AD=99=E6=98=A5=E9=98=B3?= Date: Thu, 14 Aug 2025 05:23:13 +0800 Subject: [PATCH] =?utf8?q?=E4=BC=98=E5=8C=96websocket=20parser=E8=A7=A3?= =?utf8?q?=E5=8C=85=E6=AD=A3=E7=A1=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../slip/cat1Service/cat1_ai_server.cpp | 42 +- .../peripheral/slip/cat1Service/cat1_ws.cpp | 23 +- .../slip/cat1Service/websocket_parser.cpp | 799 ++- .../slip/tcpmanager/tcp_simple_manager.c | 2 +- test_ws_parser/Makefile | 29 + test_ws_parser/websocket_analysis.py | 211 + test_ws_parser/websocket_frames_analysis.json | 5605 +++++++++++++++++ .../websocket_parser_standalone.cpp | 989 +++ test_ws_parser/websocket_simple_analysis.json | 163 + test_ws_parser/websocket_simple_analysis.py | 200 + 10 files changed, 7767 insertions(+), 296 deletions(-) create mode 100644 test_ws_parser/Makefile create mode 100644 test_ws_parser/websocket_analysis.py create mode 100644 test_ws_parser/websocket_frames_analysis.json create mode 100644 test_ws_parser/websocket_parser_standalone.cpp create mode 100644 test_ws_parser/websocket_simple_analysis.json create mode 100644 test_ws_parser/websocket_simple_analysis.py diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ai_server.cpp b/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ai_server.cpp index 7685fd358..e1aeb4c24 100644 --- a/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ai_server.cpp +++ b/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ai_server.cpp @@ -440,7 +440,6 @@ static int ws_queue_put(ws_message_queue_t* queue, const uint8_t* data, uint16_t item->type = type; item->timestamp = osKernelGetTickCount(); item->in_use = true; - printf("ws_queue_put type %d , length %d , data %s\n",type,item->length,item->data); queue->tail = (queue->tail + 1) % WS_QUEUE_SIZE; queue->count++; @@ -950,14 +949,16 @@ void bk_websocket_demo(void *data) { chat_client = init_websocket_client(url_buf, NULL, 1); if (chat_client != NULL) { chat_client->msg_queue = &chat_msg_queue; - chat_client->packet_callback = chat_on_ws_packet_callback; + ws_set_packet_callback(chat_client, chat_on_ws_packet_callback); + // chat_client->packet_callback = chat_on_ws_packet_callback; } } else { #ifdef SUPPORT_CHINA_MOBILE_AI_REGULATION chat_client = init_websocket_client(url_buf, NULL, 0); if (chat_client != NULL) { chat_client->msg_queue = &chat_msg_queue; - chat_client->packet_callback = chat_on_ws_packet_callback; + ws_set_packet_callback(chat_client, chat_on_ws_packet_callback); + // chat_client->packet_callback = chat_on_ws_packet_callback; } #else const char* base_url = "ws://118.145.158.207:22080/chat/ws"; @@ -986,7 +987,8 @@ void bk_websocket_demo(void *data) { chat_client = init_websocket_client(full_url, NULL, 0); if (chat_client != NULL) { chat_client->msg_queue = &chat_msg_queue; - chat_client->packet_callback = chat_on_ws_packet_callback; + ws_set_packet_callback(chat_client, chat_on_ws_packet_callback); + // chat_client->packet_callback = chat_on_ws_packet_callback; } #endif } @@ -1082,7 +1084,10 @@ void bk_websocket_demo(void *data) { memset_s(recv_buf, 1024, 0, 1024); int len = receive_websocket_message_from_queue(&chat_msg_queue, (unsigned char *)recv_buf, 1024, &type, AI_RECEIVE_TIMEOUT_MS); - + if (len < 1024) + { + recv_buf[len] = '\0'; + } if (len == -1 || type == WS_CLOSE) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WebSocket connection closed"); break; @@ -1102,6 +1107,10 @@ void bk_websocket_demo(void *data) { } AI_UNLOCK(); WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "recv_buf %s",recv_buf); + if (len < 1024) + { + recv_buf[len] = '\0'; + } chat_result_analysis(recv_buf); } } @@ -1479,26 +1488,30 @@ void bk_websocket_asr(void *data) { asr_client = init_websocket_client("ws://118.145.158.207:22080/asr/ws", NULL, 0); if (asr_client != NULL) { asr_client->msg_queue = &asr_msg_queue; - asr_client->packet_callback = asr_on_ws_packet_callback; + ws_set_packet_callback(asr_client, asr_on_ws_packet_callback); + // asr_client->packet_callback = asr_on_ws_packet_callback; } } else if (g_test_server_index == 2) { asr_client = init_websocket_client("ws://110.42.224.129:8910/asr/ws", NULL, 0); if (asr_client != NULL) { asr_client->msg_queue = &asr_msg_queue; - asr_client->packet_callback = asr_on_ws_packet_callback; + ws_set_packet_callback(asr_client, asr_on_ws_packet_callback); + // asr_client->packet_callback = asr_on_ws_packet_callback; } } else { if (is_raisound_url) { asr_client = init_websocket_client(url_buf, NULL, 1); if (asr_client != NULL) { asr_client->msg_queue = &asr_msg_queue; - asr_client->packet_callback = asr_on_ws_packet_callback; + ws_set_packet_callback(asr_client, asr_on_ws_packet_callback); + // asr_client->packet_callback = asr_on_ws_packet_callback; } } else { asr_client = init_websocket_client("ws://118.145.158.207:22080/asr/ws", NULL, 0); if (asr_client != NULL) { asr_client->msg_queue = &asr_msg_queue; - asr_client->packet_callback = asr_on_ws_packet_callback; + ws_set_packet_callback(asr_client, asr_on_ws_packet_callback); + // asr_client->packet_callback = asr_on_ws_packet_callback; } } } @@ -1616,7 +1629,10 @@ WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "等待ASR WebSocket握手完成... (%d m memset_s(asr_recv_buf, 1024, 0, 1024); int len = receive_websocket_message_from_queue(&asr_msg_queue, (unsigned char *)asr_recv_buf, 1024, &type, AI_RECEIVE_TIMEOUT_MS); - + if (len < 1024) + { + asr_recv_buf[len] = '\0'; + } WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "ASR received: type=%d, len=%d", type, len); if (type == WS_CLOSE || len == -1) { @@ -1958,13 +1974,15 @@ void bk_websocket_tts(void *data) { tts_client = init_websocket_client(url_buf, NULL, 1); if (tts_client != NULL) { tts_client->msg_queue = &tts_msg_queue; - tts_client->packet_callback = tts_on_ws_packet_callback; + ws_set_packet_callback(tts_client, tts_on_ws_packet_callback); + // tts_client->packet_callback = tts_on_ws_packet_callback; } } else { tts_client = init_websocket_client("ws://118.145.158.207:22080/tts/stream?audio_buffer_size=512", NULL, 0); if (tts_client != NULL) { tts_client->msg_queue = &tts_msg_queue; - tts_client->packet_callback = tts_on_ws_packet_callback; + ws_set_packet_callback(tts_client, tts_on_ws_packet_callback); + // tts_client->packet_callback = tts_on_ws_packet_callback; } } diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ws.cpp b/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ws.cpp index 4057ee22b..999cd6d3b 100644 --- a/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ws.cpp +++ b/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ws.cpp @@ -715,8 +715,8 @@ int ws_process_received_data(WebSocketClient *client, const uint8_t *data, size_ } // ========== 新增:打印收到的所有原始数据 ========== - printf("\n=== WebSocket Raw Data Received ===\n"); - printf("Client: %s:%s\n", client->host, client->path); + // printf("\n=== WebSocket Raw Data Received ===\n"); + // printf("Client: %s:%s\n", client->host, client->path); printf("Total bytes: %zu\n", len); // printf("Raw data (hex): "); // // 打印所有数据的十六进制表示 @@ -799,7 +799,7 @@ int ws_process_received_data(WebSocketClient *client, const uint8_t *data, size_ // 使用新的解析器处理当前数据段 int result = ws_parse_stream(parser, current_data, remaining_len); - if(result == -1) + if(result <= 0) { printf("ws_process_received_data: parsing error, reset parser,find next frame. Remaining: %zu bytes\n", remaining_len); ws_parser_reset(parser); @@ -828,16 +828,17 @@ int ws_process_received_data(WebSocketClient *client, const uint8_t *data, size_ if (header && payload) { printf("WebSocket frame received: opcode=0x%02X, fin=%d, payload_len=%llu\n", header->opcode, header->fin, header->payload_len); + // printf("payload = %s\n",payload); // 打印载荷数据的前几个字节(用于调试) - if (payload_len > 0) { - printf("Payload data (first 32 bytes): "); - for (size_t i = 0; i < payload_len && i < 32; i++) { - printf("%02X ", payload[i]); - } - if (payload_len > 32) printf("..."); - printf("\n"); - } + // if (payload_len > 0) { + // printf("Payload data (first 32 bytes): "); + // for (size_t i = 0; i < payload_len && i < 32; i++) { + // printf("%02X ", payload[i]); + // } + // if (payload_len > 32) printf("..."); + // printf("\n"); + // } // 根据操作码处理不同类型的消息 switch (header->opcode) { diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/websocket_parser.cpp b/code/sdk/drivers/peripheral/slip/cat1Service/websocket_parser.cpp index d695d81d1..0dda0d562 100644 --- a/code/sdk/drivers/peripheral/slip/cat1Service/websocket_parser.cpp +++ b/code/sdk/drivers/peripheral/slip/cat1Service/websocket_parser.cpp @@ -2,7 +2,21 @@ #include #include #include -#include "wearable_log.h" + +// 控制日志输出的宏 +#define ENABLE_DEBUG_LOG 1 // 设置为0可以关闭所有调试输出 + +#if ENABLE_DEBUG_LOG +#define WS_LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__) +#define WS_LOGI(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__) +#define WS_LOGD(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__) +#define WS_LOGE(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__) +#else +#define WS_LOG(fmt, ...) +#define WS_LOGI(fmt, ...) +#define WS_LOGD(fmt, ...) +#define WS_LOGE(fmt, ...) +#endif #ifdef __cplusplus extern "C" { @@ -10,27 +24,6 @@ extern "C" { /* * WebSocket协议解析器 (RFC 6455) - * - * WebSocket单帧大小限制说明: - * - * 1. 协议层面限制: - * - 16位长度字段:最大 65,535 字节 (2^16 - 1) - * - 64位长度字段:最大 18,446,744,073,709,551,615 字节 (2^64 - 1) - * - * 2. 控制帧限制(RFC 6455规定): - * - Ping/Pong帧:最大125字节负载 - * - Close帧:最大125字节负载 - * - * 3. 应用层限制: - * - 默认最大负载长度:65,535字节(16位) - * - 可配置最大负载长度:最大1MB - * - 可通过 ws_set_max_payload_length() 函数动态配置 - * - * 4. 实际限制因素: - * - 内存限制 - * - 网络MTU限制 - * - 应用层缓冲区大小 - * - 浏览器/客户端实现限制 */ // WebSocket帧类型枚举 @@ -91,27 +84,27 @@ static uint64_t g_max_payload_len = WS_MAX_PAYLOAD_LEN_DEFAULT; // 全局最大 // 初始化WebSocket解析器 ws_parser_t* ws_parser_init() { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Initializing WebSocket parser"); + WS_LOGI("WS: Initializing WebSocket parser"); ws_parser_t* parser = (ws_parser_t*)malloc(sizeof(ws_parser_t)); if (!parser) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Failed to allocate memory for parser"); + WS_LOGE("WS: Failed to allocate memory for parser"); return NULL; } // 初始化全局缓存 if (!g_ws_buffer) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Allocating global buffer (%d bytes)", WS_BUFFER_SIZE); + WS_LOGI("WS: Allocating global buffer (%d bytes)", WS_BUFFER_SIZE); g_ws_buffer = (uint8_t*)malloc(WS_BUFFER_SIZE); if (!g_ws_buffer) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Failed to allocate global buffer"); + WS_LOGE("WS: Failed to allocate global buffer"); free(parser); return NULL; } } g_parser_count++; - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser count: %d", g_parser_count); + WS_LOGI("WS: Parser count: %d", g_parser_count); // 初始化解析器状态 parser->state = WS_STATE_START; @@ -121,7 +114,7 @@ ws_parser_t* ws_parser_init() { parser->mask_pos = 0; memset(&parser->header, 0, sizeof(ws_header_t)); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser initialized successfully"); + WS_LOGI("WS: Parser initialized successfully"); return parser; } @@ -129,8 +122,6 @@ ws_parser_t* ws_parser_init() { void ws_parser_reset(ws_parser_t* parser) { if (!parser) return; - // WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Resetting parser state"); - parser->state = WS_STATE_START; parser->buffer_pos = 0; parser->payload_remaining = 0; @@ -157,19 +148,19 @@ int validate_control_frame_length(ws_opcode_t opcode, uint64_t payload_len) { // 配置最大负载长度 int ws_set_max_payload_length(uint64_t max_len) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Setting max payload length to %llu bytes", (unsigned long long)max_len); + WS_LOGI("WS: Setting max payload length to %llu bytes", (unsigned long long)max_len); if (max_len > WS_MAX_PAYLOAD_LEN_MAX) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Max payload length %llu exceeds limit %llu", + WS_LOGE("WS: Max payload length %llu exceeds limit %llu", (unsigned long long)max_len, (unsigned long long)WS_MAX_PAYLOAD_LEN_MAX); return 0; // 超过最大允许值 } if (max_len < 1) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid max payload length: %llu (must be >= 1)", (unsigned long long)max_len); + WS_LOGE("WS: Invalid max payload length: %llu (must be >= 1)", (unsigned long long)max_len); return 0; // 不能小于1字节 } g_max_payload_len = max_len; - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Max payload length set successfully"); + WS_LOGI("WS: Max payload length set successfully"); return 1; } @@ -189,7 +180,6 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { case WS_STATE_START: parser->state = WS_STATE_READ_HEADER1; // 继续执行,处理第一个字节 - // 注意:这里故意不break,让代码继续执行 case WS_STATE_READ_HEADER1:{ // 解析第一个头部字节 @@ -199,41 +189,34 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { parser->header.rsv3 = (byte >> 4) & 0x1; parser->header.opcode = (ws_opcode_t)(byte & 0x0F); - - - - // WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parse header1 - FIN:%d, RSV:%d%d%d, OPCODE:0x%02X", - // parser->header.fin, parser->header.rsv1, parser->header.rsv2, parser->header.rsv3, parser->header.opcode); - - // 检查 opcode 是否有效 if (!((parser->header.opcode >= WS_CONTINUATION && parser->header.opcode <= WS_BINARY) || (parser->header.opcode >= WS_CLOSE && parser->header.opcode <= WS_PONG))) { - // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid opcode: 0x%02X", parser->header.opcode); + WS_LOGE("WS: Invalid opcode: 0x%02X", parser->header.opcode); parser->state = WS_STATE_ERROR; return -1; } - if(parser->header.fin == 0) - { - // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid FIN bit: %d", parser->header.fin); - // parser->state = WS_STATE_ERROR; - // return -1; - } // 检查RSV位是否都为0(根据RFC6455规范) - if (parser->header.rsv1 || parser->header.rsv2 || parser->header.rsv3) { - // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid RSV bits: %d%d%d", - // parser->header.rsv1, parser->header.rsv2, parser->header.rsv3); - // parser->state = WS_STATE_ERROR; - // return -1; + if (!(parser->header.fin == 1 && parser->header.rsv1 == 0 && parser->header.rsv2 == 0 && parser->header.rsv3 == 0)) + { + WS_LOGE("WS: Invalid RSV bits: %d%d%d", + parser->header.rsv1, parser->header.rsv2, parser->header.rsv3); + parser->state = WS_STATE_ERROR; + return -1; } + WS_LOGD("WS: Parse header1 - FIN:%d, RSV:%d%d%d, OPCODE:0x%02X", + parser->header.fin, parser->header.rsv1, parser->header.rsv2, parser->header.rsv3, parser->header.opcode); + + + // 保存第一个头部字节到缓存 if (parser->buffer_pos < WS_BUFFER_SIZE) { parser->buffer[parser->buffer_pos++] = byte; } else { parser->state = WS_STATE_ERROR; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in header1"); + WS_LOGE("WS: Buffer overflow in header1"); return -1; } @@ -246,7 +229,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { parser->header.mask = (byte >> 7) & 0x1; uint8_t payload_len = byte & 0x7F; - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "WS: Parse header2 - MASK:%d, LEN:%d", + WS_LOGD("WS: Parse header2 - MASK:%d, LEN:%d", parser->header.mask, payload_len); // 保存第二个头部字节到缓存 @@ -254,7 +237,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { parser->buffer[parser->buffer_pos++] = byte; } else { parser->state = WS_STATE_ERROR; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in header2"); + WS_LOGE("WS: Buffer overflow in header2"); return -1; } @@ -263,11 +246,11 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { parser->header.payload_len = payload_len; parser->payload_remaining = payload_len; - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Small payload length: %d bytes", payload_len); + WS_LOGI("WS: Small payload length: %d bytes", payload_len); // 验证控制帧长度 if (!validate_control_frame_length(parser->header.opcode, payload_len)) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Control frame length validation failed: opcode=0x%02X, len=%d", + WS_LOGE("WS: Control frame length validation failed: opcode=0x%02X, len=%d", parser->header.opcode, payload_len); parser->state = WS_STATE_ERROR; return -1; @@ -286,13 +269,13 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { } } else if (payload_len == 126) { // 16位长度,需要再读取2个字节 - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Extended 16-bit payload length mode"); + WS_LOGI("WS: Extended 16-bit payload length mode"); parser->header.payload_len = 126; // 临时标记 parser->payload_remaining = 2; parser->state = WS_STATE_READ_PAYLOAD_LEN; } else if (payload_len == 127) { // 64位长度,需要再读取8个字节 - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Extended 64-bit payload length mode"); + WS_LOGI("WS: Extended 64-bit payload length mode"); parser->header.payload_len = 127; // 临时标记 parser->payload_remaining = 8; parser->state = WS_STATE_READ_PAYLOAD_LEN; @@ -301,21 +284,21 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { } case WS_STATE_READ_PAYLOAD_LEN: { - // 保存长度字节到缓存 - if (parser->buffer_pos < WS_BUFFER_SIZE) { - parser->buffer[parser->buffer_pos++] = byte; - } else { - parser->state = WS_STATE_ERROR; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in payload length"); - return -1; - } + // // 保存长度字节到缓存 + // if (parser->buffer_pos < WS_BUFFER_SIZE) { + // parser->buffer_pos++; + // } else { + // parser->state = WS_STATE_ERROR; + // WS_LOGE("WS: Buffer overflow in payload length"); + // return -1; + // } - // 累加长度数据 - 修复:使用正确的索引计算 + // 累加长度数据 static uint8_t len_bytes[8]; - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "WS: Reading payload length byte: 0x%02X, remaining: %zu", + WS_LOGD("WS: Reading payload length byte: 0x%02X, remaining: %zu", byte, parser->payload_remaining); - + if (parser->header.payload_len == 126) { // 16位扩展长度:只需要2个字节 // 第一个字节存储在len_bytes[0],第二个字节存储在len_bytes[1] @@ -328,24 +311,26 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { parser->payload_remaining--; if (parser->payload_remaining == 0) { - // 计算16位长度 - 修复:使用正确的字节顺序 - // 注意:网络字节序是大端序,第一个字节是高字节 - parser->header.payload_len = (len_bytes[0] << 8) | len_bytes[1]; - parser->payload_remaining = parser->header.payload_len; + // 计算16位长度 + uint16_t _payload_len = (uint16_t)(len_bytes[0] <<8 ) + len_bytes[1]; + printf("len_bytes[0] = %d, len_bytes[1] = %d\n ,payload_len = %d\n", len_bytes[0], len_bytes[1],_payload_len); + + parser->header.payload_len = _payload_len; + parser->payload_remaining = _payload_len; - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: 16-bit payload length: %d bytes (0x%02X%02X)", - parser->header.payload_len, len_bytes[0], len_bytes[1]); + WS_LOGI("WS: 16-bit payload length: %d bytes (0x%02X%02X)", + parser->header.payload_len, len_bytes[1], len_bytes[0]); // 验证控制帧长度 if (!validate_control_frame_length(parser->header.opcode, parser->header.payload_len)) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Control frame length validation failed for 16-bit length"); + WS_LOGE("WS: Control frame length validation failed for 16-bit length"); parser->state = WS_STATE_ERROR; return -1; } // 检查负载长度是否合理 if (parser->header.payload_len > g_max_payload_len) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Payload length %d exceeds maximum %llu", + WS_LOGE("WS: Payload length %d exceeds maximum %llu", parser->header.payload_len, (unsigned long long)g_max_payload_len); parser->state = WS_STATE_ERROR; return -1; @@ -353,7 +338,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { // 检查缓存是否足够 if (parser->buffer_pos + parser->header.payload_len > WS_BUFFER_SIZE) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow: current=%zu, adding=%d, max=%d", + WS_LOGE("WS: Buffer overflow: current=%zu, adding=%d, max=%d", parser->buffer_pos, parser->header.payload_len, WS_BUFFER_SIZE); parser->state = WS_STATE_ERROR; return -1; @@ -361,21 +346,20 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { // 处理掩码 if (parser->header.mask) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Moving to READ_MASK state"); + WS_LOGI("WS: Moving to READ_MASK state"); parser->state = WS_STATE_READ_MASK; } else { if (parser->payload_remaining == 0) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Zero payload, moving to COMPLETE state"); + WS_LOGI("WS: Zero payload, moving to COMPLETE state"); parser->state = WS_STATE_COMPLETE; return 1; } - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Moving to READ_PAYLOAD state"); + WS_LOGI("WS: Moving to READ_PAYLOAD state"); parser->state = WS_STATE_READ_PAYLOAD; } } } else if (parser->header.payload_len == 127) { // 64位扩展长度:需要8个字节 - // 使用正确的索引:从0开始,按顺序存储 size_t byte_index = 8 - parser->payload_remaining; len_bytes[byte_index] = byte; @@ -389,43 +373,44 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { } parser->payload_remaining = parser->header.payload_len; - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: 64-bit payload length: %llu bytes", + WS_LOGI("WS: 64-bit payload length: %llu bytes", (unsigned long long)parser->header.payload_len); // 验证控制帧长度 if (!validate_control_frame_length(parser->header.opcode, parser->header.payload_len)) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Control frame length validation failed for 64-bit length"); + WS_LOGE("WS: Control frame length validation failed for 64-bit length"); parser->state = WS_STATE_ERROR; return -1; } // 检查负载长度是否合理 if (parser->header.payload_len > g_max_payload_len) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: 64-bit payload length %llu exceeds maximum %llu", - parser->header.payload_len, (unsigned long long)g_max_payload_len); + WS_LOGE("WS: Payload length %llu exceeds maximum %llu", + (unsigned long long)parser->header.payload_len, (unsigned long long)g_max_payload_len); parser->state = WS_STATE_ERROR; return -1; } // 检查缓存是否足够 if (parser->buffer_pos + parser->header.payload_len > WS_BUFFER_SIZE) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow: current=%zu, adding=%llu, max=%d", - parser->buffer_pos, parser->header.payload_len, WS_BUFFER_SIZE); + WS_LOGE("WS: Buffer overflow: current=%zu, adding=%llu, max=%d", + parser->buffer_pos, (unsigned long long)parser->header.payload_len, WS_BUFFER_SIZE); parser->state = WS_STATE_ERROR; return -1; } // 处理掩码 if (parser->header.mask) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Moving to READ_MASK state"); + WS_LOGI("WS: Moving to READ_MASK state"); parser->state = WS_STATE_READ_MASK; + return 1; } else { if (parser->payload_remaining == 0) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Zero payload, moving to COMPLETE state"); + WS_LOGI("WS: Zero payload, moving to COMPLETE state"); parser->state = WS_STATE_COMPLETE; return 1; } - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Moving to READ_PAYLOAD state"); + WS_LOGI("WS: Moving to READ_PAYLOAD state"); parser->state = WS_STATE_READ_PAYLOAD; } } @@ -433,270 +418,540 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { break; } - case WS_STATE_READ_MASK: + case WS_STATE_READ_MASK: { // 读取掩码密钥 - parser->header.mask_key[parser->mask_pos++] = byte; - - // 保存掩码字节到缓存 + if (parser->mask_pos < 4) { + parser->header.mask_key[parser->mask_pos++] = byte; + // 保存掩码字节到缓存 if (parser->buffer_pos < WS_BUFFER_SIZE) { parser->buffer[parser->buffer_pos++] = byte; } else { parser->state = WS_STATE_ERROR; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in mask"); + WS_LOGI("WS: Buffer overflow in mask"); return -1; } // 掩码密钥共4字节 - if (parser->mask_pos == 4) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Mask key read: %02X %02X %02X %02X", - parser->header.mask_key[0], parser->header.mask_key[1], - parser->header.mask_key[2], parser->header.mask_key[3]); - - if (parser->payload_remaining == 0) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Frame parsing complete (zero payload)"); - parser->state = WS_STATE_COMPLETE; - return 1; + if (parser->mask_pos == 4) { + WS_LOGI("WS: Mask key read complete: 0x%02X%02X%02X%02X", + parser->header.mask_key[0], parser->header.mask_key[1], + parser->header.mask_key[2], parser->header.mask_key[3]); + + if (parser->payload_remaining == 0) { + parser->state = WS_STATE_COMPLETE; + return 1; + } + parser->state = WS_STATE_READ_PAYLOAD; } - parser->state = WS_STATE_READ_PAYLOAD; } break; + } case WS_STATE_READ_PAYLOAD: { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "WS: Reading payload byte, remaining: %zu, buffer_pos: %zu", - parser->payload_remaining, parser->buffer_pos); - - // 保存负载字节到缓存 + // 读取负载数据 if (parser->buffer_pos < WS_BUFFER_SIZE) { parser->buffer[parser->buffer_pos++] = byte; + parser->payload_remaining--; + + if (parser->payload_remaining == 0) { + // 负载读取完成 + WS_LOGI("WS: Payload read complete (%zu bytes)", parser->header.payload_len); + + // 如果有掩码,应用掩码解码 + if (parser->header.mask) { + // 计算负载在缓存中的起始位置 + size_t payload_start = parser->buffer_pos - parser->header.payload_len; + apply_mask(parser->buffer + payload_start, parser->header.payload_len, + parser->header.mask_key, 0); + WS_LOGI("WS: Mask applied to payload"); + } + + parser->state = WS_STATE_COMPLETE; + return 1; + } } else { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in payload reading"); parser->state = WS_STATE_ERROR; + WS_LOGE("WS: Buffer overflow in payload"); return -1; } - - parser->payload_remaining--; - - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "WS: After reading byte, remaining: %zu, buffer_pos: %zu", - parser->payload_remaining, parser->buffer_pos); - - // 所有负载都已读取 - if (parser->payload_remaining == 0) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Payload read complete (%llu bytes)", - (unsigned long long)parser->header.payload_len); - - // 如果有掩码,对负载数据进行解码 - if (parser->header.mask) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Applying mask to payload data"); - size_t payload_start = parser->buffer_pos - parser->header.payload_len; - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Payload start: %zu, payload length: %llu", - payload_start, parser->header.payload_len); - apply_mask(parser->buffer + payload_start, - parser->header.payload_len, - parser->header.mask_key, - 0); - } - - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Frame parsing complete, transitioning to COMPLETE state"); - parser->state = WS_STATE_COMPLETE; - return 1; - } break; } + case WS_STATE_COMPLETE: + WS_LOGI("WS: Frame parsing complete, transitioning to COMPLETE state"); + return 1; + + case WS_STATE_ERROR: + WS_LOGE("WS: Parser is in error state"); + return -1; + default: - break; + WS_LOGE("WS: Unknown parser state: %d", parser->state); + parser->state = WS_STATE_ERROR; + return -1; } - return 0; + return 0; // 继续解析 } -// 处理流数据输入 -// 返回值:解析出的完整包长度,0-未完成,-1-错误 +// 解析数据流 int ws_parse_stream(ws_parser_t* parser, const uint8_t* data, size_t len) { if (!parser || !data || len == 0) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid parameters for stream parsing"); + WS_LOGE("WS: Invalid parameters for ws_parse_stream"); return -1; } - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parsing stream data (%zu bytes), current state: %d, buffer_pos: %zu", - len, parser->state, parser->buffer_pos); + WS_LOGI("WS: Parsing stream data (%zu bytes), current state: %d, buffer_pos: %zu", + len, parser->state, parser->buffer_pos); - // 重要:如果解析器状态为COMPLETE,说明上一个帧已经完成 - // 新数据应该开始解析新的帧,需要重置解析器状态 + // 如果解析器已经完成一个帧,重置状态 if (parser->state == WS_STATE_COMPLETE) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser was in COMPLETE state, resetting for new frame"); + WS_LOGI("WS: Parser was in COMPLETE state, resetting for new frame"); ws_parser_reset(parser); } - size_t i=0; - for (i = 0; i < len; i++) { + + int total_processed = 0; + + for (size_t i = 0; i < len; i++) { int result = ws_parse_byte(parser, data[i]); if (result == 1) { - // 解析完成一个包 - int packet_len = parser->buffer_pos; - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Complete frame parsed (%d bytes total) opcode: %d, payload_len: %llu", - packet_len, parser->header.opcode, parser->header.payload_len); - - // 重要:不要在这里重置解析器! - // 让上层处理完数据后再调用 ws_parser_reset() - // 这样可以确保数据被正确处理后再清理状态 - return i+1; + // 帧解析完成 + WS_LOGI("WS: Complete frame parsed (%zu bytes total) opcode: %d, payload_len: %llu", + parser->buffer_pos, parser->header.opcode, (unsigned long long)parser->header.payload_len); + total_processed = i + 1; + break; } else if (result == -1) { - // 解析错误,重置解析器 - // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Parse error at byte %zu, resetting parser, byte: %02X", i, data[i]); + // 解析错误 + WS_LOGE("WS: Parsing error at byte %zu", i); ws_parser_reset(parser); - continue; + // return -1; + total_processed = i + 1; } + // result == 0 继续解析 } - // 未完成解析,显示当前状态信息 - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Frame parsing incomplete, waiting for more data. State: %d, Buffer: %zu/%zu, Payload remaining: %zu", - parser->state, parser->buffer_pos, WS_BUFFER_SIZE, parser->payload_remaining); - return i+1; + if (parser->state == WS_STATE_COMPLETE) { + WS_LOGI(" WS_STATE_COMPLETE at %d\n",total_processed); + } else if (parser->state == WS_STATE_ERROR) { + WS_LOGI(" WS_STATE_ERROR at %d\n",total_processed); + } else { + // 数据不完整,继续等待更多数据 + WS_LOGI("WS: Frame parsing incomplete, waiting for more data. State: %d, Buffer: %zu/%d, Payload remaining: %zu", + parser->state, parser->buffer_pos, WS_BUFFER_SIZE, parser->payload_remaining); + } + return total_processed; } -// 新增:打印解析器详细状态信息(用于调试) -void ws_parser_debug_state(ws_parser_t* parser) { - if (!parser) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Cannot debug NULL parser"); - return; +// 获取解析出的头部信息 +const ws_header_t* ws_get_header(ws_parser_t* parser) { + if (!parser || parser->state != WS_STATE_COMPLETE) { + return NULL; + } + return &parser->header; +} + +// 获取完整数据包(包含帧头) +const uint8_t* ws_get_packet(ws_parser_t* parser) { + if (!parser || parser->state != WS_STATE_COMPLETE) { + return NULL; + } + return parser->buffer; +} + +// 获取纯载荷数据 +const uint8_t* ws_get_payload(ws_parser_t* parser) { + if (!parser || parser->state != WS_STATE_COMPLETE) { + return NULL; } - const char* state_names[] = { - "START", "READ_HEADER1", "READ_HEADER2", "READ_PAYLOAD_LEN", - "READ_MASK", "READ_PAYLOAD", "COMPLETE", "ERROR" - }; + // 计算载荷数据的起始位置 + // 帧头:2字节(基本头部) + size_t header_size = 2; - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser Debug State:"); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " State: %s (%d)", - state_names[parser->state], parser->state); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " Buffer Position: %zu/%d", - parser->buffer_pos, WS_BUFFER_SIZE); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " Payload Remaining: %zu", - parser->payload_remaining); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " Mask Position: %zu", - parser->mask_pos); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " Header Info:"); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " FIN: %d", parser->header.fin); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " Opcode: 0x%02X", parser->header.opcode); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " Mask: %d", parser->header.mask); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " Payload Length: %llu", - (unsigned long long)parser->header.payload_len); + // 扩展长度字段 + if (parser->header.payload_len == 126) { + header_size += 2; // 16位长度 + } else if (parser->header.payload_len == 127) { + header_size += 8; // 64位长度 + } + // 掩码密钥 if (parser->header.mask) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " Mask Key: %02X %02X %02X %02X", - parser->header.mask_key[0], parser->header.mask_key[1], - parser->header.mask_key[2], parser->header.mask_key[3]); + header_size += 4; } - // 打印缓冲区前几个字节(用于调试) - if (parser->buffer_pos > 0) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, " Buffer (first 16 bytes):"); - for (size_t i = 0; i < parser->buffer_pos && i < 16; i++) { - printf("%02X ", parser->buffer[i]); - } - if (parser->buffer_pos > 16) printf("..."); - printf("\n"); + // 检查载荷数据是否在缓存范围内 + if (header_size + parser->header.payload_len > parser->buffer_pos) { + WS_LOGE("WS: Payload start position %zu exceeds buffer size %zu", header_size, parser->buffer_pos); + return NULL; } + + return parser->buffer + header_size; } -// 新增:手动重置解析器状态(供上层调用) -void ws_parser_manual_reset(ws_parser_t* parser) { - if (!parser) { - WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "WS: Attempt to manually reset NULL parser"); - return; +// 获取载荷数据长度 +size_t ws_get_payload_length(ws_parser_t* parser) { + if (!parser || parser->state != WS_STATE_COMPLETE) { + return 0; } - - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Manual parser reset requested"); - ws_parser_reset(parser); + return parser->header.payload_len; +} + +// 检查解析器是否有错误 +int ws_parser_has_error(ws_parser_t* parser) { + return (parser && parser->state == WS_STATE_ERROR) ? 1 : 0; } -// 释放解析器资源 +// 获取解析器当前状态 +ws_parse_state_t ws_parser_get_state(ws_parser_t* parser) { + return parser ? parser->state : WS_STATE_ERROR; +} + +// 销毁解析器 void ws_parser_destroy(ws_parser_t* parser) { if (parser) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Destroying WebSocket parser"); free(parser); g_parser_count--; - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser count after destroy: %d", g_parser_count); - - // 只有当没有解析器实例时才释放全局缓存 + // 如果所有解析器都被销毁,释放全局缓存 if (g_parser_count == 0 && g_ws_buffer) { - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Releasing global buffer (last parser destroyed)"); free(g_ws_buffer); g_ws_buffer = NULL; + WS_LOGI("WS: Global buffer freed"); } - } else { - WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "WS: Attempt to destroy NULL parser"); + + WS_LOGI("WS: Parser destroyed, remaining parsers: %d", g_parser_count); } } -// 获取解析出的头部信息 -const ws_header_t* ws_get_header(ws_parser_t* parser) { - if (!parser) return NULL; - return &parser->header; -} - -// 获取解析出的完整数据包(包含帧头,用于调试) -const uint8_t* ws_get_packet(ws_parser_t* parser) { - if (!parser) return NULL; - return parser->buffer; +#ifdef __cplusplus } - -// 新增:获取纯载荷数据(不包含帧头) -const uint8_t* ws_get_payload(ws_parser_t* parser) { - if (!parser || parser->state != WS_STATE_COMPLETE) return NULL; +#endif +#if 0 +// 多包拆解测试函数 +void test_multiple_frames() { + printf("\n=== Multiple WebSocket Frames Test ===\n"); - // 计算载荷数据的起始位置 - size_t payload_start = 0; + // 测试数据:包含多个WebSocket帧 + uint8_t test_data[] = { + // 第一个帧:5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第二个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 E6 A0 B7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF, + 0x99, 0xE6, 0xA0, 0xB7, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第三个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 74, 0x22, 0x3A, 0x22, 0xE7, 0x9A, + 0x84, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第四个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 95 B0 E5 AD 97 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x95, + 0xB0, 0xE5, 0xAD, 0x97, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第五个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 BB 84 E5 90 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE7, 0xBB, + 0x84, 0xE5, 0x90, 0x88, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第六个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 A2 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x91, + 0xA2, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第七个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E3 80 82 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE3, 0x80, + 0x82, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第八个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE4, 0xBD, + 0xA0, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第九个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 83 BD 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0x83, + 0xBD, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xAF, + 0xB4, 0xE8, 0xAF, 0xB4, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十一个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF, + 0x99, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十二个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 87 A0 E4 B8 AA 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x87, + 0xA0, 0xE4, 0xB8, 0xAA, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十三个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 95 B0 E5 AD 97 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x95, + 0xB0, 0xE5, 0xAD, 0x97, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十四个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 98 AF 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x98, + 0xAF, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十五个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 9C A8 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x9C, + 0xA8, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D + }; - // 基本头部:2字节 - payload_start += 2; + size_t test_data_len = sizeof(test_data); - // 扩展长度字段 - uint8_t payload_len_initial = parser->buffer[1] & 0x7F; - if (payload_len_initial == 126) { - payload_start += 2; // 16位长度 - } else if (payload_len_initial == 127) { - payload_start += 8; // 64位长度 + printf("Test data length: %zu bytes\n", test_data_len); + printf("Test data (hex): "); + for (size_t i = 0; i < test_data_len; i++) { + printf("%02X ", test_data[i]); + if ((i + 1) % 16 == 0) printf("\n "); } + printf("\n"); - // 掩码密钥(如果存在) - if (parser->header.mask) { - payload_start += 4; + // 创建解析器 + ws_parser_t* parser = ws_parser_init(); + if (!parser) { + printf("Failed to create parser\n"); + return; } - // 确保不越界 - if (payload_start >= parser->buffer_pos) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Payload start position %zu exceeds buffer size %zu", - payload_start, parser->buffer_pos); - return NULL; - } + // 多包拆解测试 + printf("\n=== Starting Multi-Frame Parsing ===\n"); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Payload data starts at offset %zu, length %llu", - payload_start, parser->header.payload_len); + size_t offset = 0; + int frame_count = 0; - return parser->buffer + payload_start; -} + while (offset < test_data_len) { + printf("\n--- Frame %d ---\n", frame_count + 1); + printf("Remaining data: %zu bytes\n", test_data_len - offset); + + // 解析当前帧 + int result = ws_parse_stream(parser, test_data + offset, test_data_len - offset); + ws_parse_state_t ws_state = ws_parser_get_state(parser); + printf("ws_state: %d,result: %d\n", ws_state,result); + if (result > 0 && ws_state == WS_STATE_COMPLETE) { + frame_count++; + printf("Frame %d parsed successfully, consumed %d bytes\n", frame_count, result); + + const ws_header_t* header = ws_get_header(parser); + if (header) { + printf("Frame header:\n"); + printf(" FIN: %d\n", header->fin); + printf(" RSV: %d%d%d\n", header->rsv1, header->rsv2, header->rsv3); + printf(" Opcode: 0x%02X\n", header->opcode); + printf(" Mask: %d\n", header->mask); + printf(" Payload length: %llu\n", (unsigned long long)header->payload_len); + + if (header->mask) { + printf(" Mask key: 0x%02X%02X%02X%02X\n", + header->mask_key[0], header->mask_key[1], + header->mask_key[2], header->mask_key[3]); + } + } + + const uint8_t* payload = ws_get_payload(parser); + size_t payload_len = ws_get_payload_length(parser); + + if (payload && payload_len > 0) { + printf("Payload data:\n"); + printf(" Length: %zu bytes\n", payload_len); + printf(" Hex: "); + for (size_t i = 0; i < payload_len && i < 32; i++) { + printf("%02X ", payload[i]); + if ((i + 1) % 16 == 0) printf("\n "); + } + if (payload_len > 32) printf("..."); + printf("\n"); + + printf(" ASCII: "); + for (size_t i = 0; i < payload_len && i < 64; i++) { + if (payload[i] >= 32 && payload[i] <= 126) { + printf("%c", payload[i]); + } else { + printf("."); + } + } + if (payload_len > 64) printf("..."); + printf("\n"); + } + + + + // 重置解析器状态,准备解析下一个帧 + ws_parser_reset(parser); + + } else if (result > 0 && ws_state != WS_STATE_ERROR) { + printf("Parser state: %d reset \n", ws_parser_get_state(parser)); + // 重置解析器状态,准备解析下一个帧 + ws_parser_reset(parser); + } else { + printf("Incomplete frame, need more data\n"); + // printf("Parse error at offset %zu\n", offset); + // printf("Parser state: %d\n", ws_parser_get_state(parser)); + } -// 新增:获取载荷数据长度 -size_t ws_get_payload_length(ws_parser_t* parser) { - if (!parser || parser->state != WS_STATE_COMPLETE) return 0; - return parser->header.payload_len; + // 移动到下一个帧 + offset += result; + // 添加安全检查 + if (offset >= test_data_len) { + printf("Reached end of data\n"); + break; + } + } + + printf("\n=== Multi-Frame Parsing Complete ===\n"); + printf("Total frames parsed: %d\n", frame_count); + printf("Total bytes processed: %zu\n", offset); + printf("Remaining bytes: %zu\n", test_data_len - offset); + + // 清理 + ws_parser_destroy(parser); } -// 新增:检查解析器是否处于错误状态 -int ws_parser_has_error(ws_parser_t* parser) { - if (!parser) return 1; - return (parser->state == WS_STATE_ERROR); +// 单帧测试函数(保留原有功能) +void test_single_frame() { + printf("\n=== Single WebSocket Frame Test ===\n"); + + // 测试数据:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 E6 A0 B7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + uint8_t test_data[] = { + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF, + 0x99, 0xE6, 0xA0, 0xB7, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D + }; + + size_t test_data_len = sizeof(test_data); + + printf("Test data length: %zu bytes\n", test_data_len); + printf("Test data (hex): "); + for (size_t i = 0; i < test_data_len; i++) { + printf("%02X ", test_data[i]); + if ((i + 1) % 16 == 0) printf("\n "); + } + printf("\n"); + + // 创建解析器 + ws_parser_t* parser = ws_parser_init(); + if (!parser) { + printf("Failed to create parser\n"); + return; + } + + // 解析数据 + int result = ws_parse_stream(parser, test_data, test_data_len); + + if (result > 0) { + printf("\n=== Parse Result ===\n"); + printf("Parsed bytes: %d\n", result); + + const ws_header_t* header = ws_get_header(parser); + if (header) { + printf("Frame header:\n"); + printf(" FIN: %d\n", header->fin); + printf(" RSV: %d%d%d\n", header->rsv1, header->rsv2, header->rsv3); + printf(" Opcode: 0x%02X\n", header->opcode); + printf(" Mask: %d\n", header->mask); + printf(" Payload length: %llu\n", (unsigned long long)header->payload_len); + + if (header->mask) { + printf(" Mask key: 0x%02X%02X%02X%02X\n", + header->mask_key[0], header->mask_key[1], + header->mask_key[2], header->mask_key[3]); + } + } + + const uint8_t* payload = ws_get_payload(parser); + size_t payload_len = ws_get_payload_length(parser); + + if (payload && payload_len > 0) { + printf("\nPayload data:\n"); + printf(" Length: %zu bytes\n", payload_len); + printf(" Hex: "); + for (size_t i = 0; i < payload_len && i < 64; i++) { + printf("%02X ", payload[i]); + if ((i + 1) % 16 == 0) printf("\n "); + } + if (payload_len > 64) printf("..."); + printf("\n"); + + printf(" ASCII: "); + for (size_t i = 0; i < payload_len && i < 64; i++) { + if (payload[i] >= 32 && payload[i] <= 126) { + printf("%c", payload[i]); + } else { + printf("."); + } + } + if (payload_len > 64) printf("..."); + printf("\n"); + } + + printf("\nParser state: %d\n", ws_parser_get_state(parser)); + + } else if (result == 0) { + printf("Incomplete frame, need more data\n"); + printf("Parser state: %d\n", ws_parser_get_state(parser)); + } else { + printf("Parse error\n"); + printf("Parser state: %d\n", ws_parser_get_state(parser)); + } + + // 清理 + ws_parser_destroy(parser); } -// 新增:获取当前解析状态 -ws_parse_state_t ws_parser_get_state(ws_parser_t* parser) { - if (!parser) return WS_STATE_ERROR; - return parser->state; +int main() { + printf("WebSocket Parser Standalone Test\n"); + printf("================================\n"); + + // 测试单帧解析 + test_single_frame(); + + // 测试多帧解析 + test_multiple_frames(); + + printf("\nAll tests completed.\n"); + return 0; } -#ifdef __cplusplus -} -#endif +#endif \ No newline at end of file diff --git a/code/sdk/drivers/peripheral/slip/tcpmanager/tcp_simple_manager.c b/code/sdk/drivers/peripheral/slip/tcpmanager/tcp_simple_manager.c index eaf50b52d..03cec756b 100644 --- a/code/sdk/drivers/peripheral/slip/tcpmanager/tcp_simple_manager.c +++ b/code/sdk/drivers/peripheral/slip/tcpmanager/tcp_simple_manager.c @@ -1554,7 +1554,7 @@ int tcp_send_and_wait_response(tcp_handle_t handle, const uint8_t* send_data, ui continue; } else if (errno == EINPROGRESS) { /* 连接正在进行中,等待连接完成 */ - printf("tcp_send_and_wait_response: 连接正在进行中,等待连接完成...\n"); + // printf("tcp_send_and_wait_response: 连接正在进行中,等待连接完成...\n"); if ((sys_now() - start_time) > timeout_ms) { printf("tcp_send_and_wait_response: 等待连接完成超时\n"); return -1; diff --git a/test_ws_parser/Makefile b/test_ws_parser/Makefile new file mode 100644 index 000000000..99a8e6d62 --- /dev/null +++ b/test_ws_parser/Makefile @@ -0,0 +1,29 @@ +CC = gcc +CFLAGS = -Wall -Wextra -std=c99 -O2 +TARGET = websocket_test +SOURCE = websocket_parser_standalone.cpp + +# 默认目标 +all: $(TARGET) + +# 编译目标 +$(TARGET): $(SOURCE) + $(CC) $(CFLAGS) -o $(TARGET) $(SOURCE) + +# 清理 +clean: + rm -f $(TARGET) + +# 运行测试 +test: $(TARGET) + ./$(TARGET) + +# 显示帮助 +help: + @echo "Available targets:" + @echo " all - Build the test program" + @echo " clean - Remove build artifacts" + @echo " test - Build and run the test" + @echo " help - Show this help message" + +.PHONY: all clean test help \ No newline at end of file diff --git a/test_ws_parser/websocket_analysis.py b/test_ws_parser/websocket_analysis.py new file mode 100644 index 000000000..203fcde89 --- /dev/null +++ b/test_ws_parser/websocket_analysis.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +WebSocket数据解析工具 +分析十六进制数据,识别WebSocket帧结构,生成JSON报告 +""" + +import json +import re +from typing import List, Dict, Any + +class WebSocketFrameAnalyzer: + def __init__(self): + self.frames = [] + + def hex_to_bytes(self, hex_string: str) -> bytes: + """将十六进制字符串转换为字节""" + # 移除空格和换行符 + hex_string = re.sub(r'\s+', '', hex_string) + return bytes.fromhex(hex_string) + + def analyze_websocket_frame(self, data: bytes, offset: int) -> Dict[str, Any]: + """分析单个WebSocket帧""" + if len(data) < 2: + return None + + # 解析第一个字节 + first_byte = data[0] + fin = (first_byte >> 7) & 0x1 + rsv = (first_byte >> 4) & 0x7 + opcode = first_byte & 0x0F + + # 解析第二个字节 + second_byte = data[1] + mask = (second_byte >> 7) & 0x1 + payload_len = second_byte & 0x7F + + # 计算帧头大小 + header_size = 2 + + # 扩展长度字段 + if payload_len == 126: + if len(data) >= 4: + extended_len = int.from_bytes(data[2:4], 'big') + header_size += 2 + else: + extended_len = 0 + elif payload_len == 127: + if len(data) >= 10: + extended_len = int.from_bytes(data[2:10], 'big') + header_size += 8 + else: + extended_len = 0 + else: + extended_len = payload_len + + # 掩码密钥 + if mask: + header_size += 4 + + # 计算总帧大小 + total_frame_size = header_size + extended_len + + # 检查数据是否完整 + if len(data) < total_frame_size: + return None + + # 提取负载数据 + payload_data = data[header_size:header_size + extended_len] + + # 如果有掩码,需要解掩码 + if mask and len(data) >= header_size + 4: + mask_key = data[header_size - 4:header_size] + unmasked_payload = bytearray(extended_len) + for i in range(extended_len): + unmasked_payload[i] = payload_data[i] ^ mask_key[i % 4] + payload_data = bytes(unmasked_payload) + + # 解析JSON内容(如果可能) + json_content = None + try: + if payload_data: + json_content = json.loads(payload_data.decode('utf-8')) + except: + pass + + # 构建帧信息 + frame_info = { + "frame_index": len(self.frames), + "offset_in_stream": offset, + "frame_header": { + "fin": fin, + "rsv": rsv, + "opcode": opcode, + "opcode_name": self.get_opcode_name(opcode), + "mask": mask, + "payload_length": extended_len + }, + "frame_structure": { + "header_size": header_size, + "total_frame_size": total_frame_size, + "payload_size": extended_len + }, + "raw_data": { + "hex": data[:total_frame_size].hex(' ').upper(), + "bytes": list(data[:total_frame_size]) + }, + "payload": { + "hex": payload_data.hex(' ').upper() if payload_data else "", + "bytes": list(payload_data) if payload_data else [], + "utf8": payload_data.decode('utf-8', errors='ignore') if payload_data else "", + "json": json_content + } + } + + return frame_info, total_frame_size + + def get_opcode_name(self, opcode: int) -> str: + """获取操作码名称""" + opcode_names = { + 0x0: "CONTINUATION", + 0x1: "TEXT", + 0x2: "BINARY", + 0x8: "CLOSE", + 0x9: "PING", + 0xA: "PONG" + } + return opcode_names.get(opcode, f"UNKNOWN(0x{opcode:02X})") + + def analyze_stream(self, hex_data: str) -> List[Dict[str, Any]]: + """分析整个数据流""" + data = self.hex_to_bytes(hex_data) + offset = 0 + + print(f"分析数据流,总长度: {len(data)} 字节") + + while offset < len(data): + remaining_data = data[offset:] + + # 尝试解析一个帧 + result = self.analyze_websocket_frame(remaining_data, offset) + + if result is None: + # 无法解析,跳过1字节 + offset += 1 + continue + + frame_info, frame_size = result + + # 添加到帧列表 + self.frames.append(frame_info) + + print(f"发现帧 {len(self.frames)}: {frame_info['frame_header']['opcode_name']} " + f"(FIN={frame_info['frame_header']['fin']}, " + f"长度={frame_info['frame_structure']['total_frame_size']} 字节)") + + # 移动到下一个帧 + offset += frame_size + + print(f"总共发现 {len(self.frames)} 个WebSocket帧") + return self.frames + + def save_to_json(self, filename: str): + """保存分析结果到JSON文件""" + output = { + "analysis_summary": { + "total_frames": len(self.frames), + "total_bytes": sum(frame["frame_structure"]["total_frame_size"] for frame in self.frames) + }, + "frames": self.frames + } + + with open(filename, 'w', encoding='utf-8') as f: + json.dump(output, f, ensure_ascii=False, indent=2) + + print(f"分析结果已保存到: {filename}") + +def main(): + # 原始十六进制数据 + hex_data = """65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E + 74 65 6E 74 22 3A 22 EF BC 8C 22 2C 22 74 61 73 + 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E + 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 B8 80 E5 AE 9A 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BE 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 84 89 E5 BF AB 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BF 83 E6 83 85 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 90 A7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F 98 98 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 43 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 20 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 8F AF E4 BB A5 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 92 8C 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 88 91 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BB 80 E4 B9 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BA 8B 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 80 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F A7 90 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 41 7B 22 74 79 70 65 22 3A 22 65 6E 64 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 6E 75 6C 6C 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 81 7E 00 BB 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 39 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E4 BB 96 E4 BD A0 22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 C4 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 CD 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D""" + + # 创建分析器 + analyzer = WebSocketFrameAnalyzer() + + # 分析数据流 + frames = analyzer.analyze_stream(hex_data) + + # 保存到JSON文件 + analyzer.save_to_json("websocket_frames_analysis.json") + + # 打印简要统计 + print("\n=== 分析统计 ===") + print(f"总帧数: {len(frames)}") + print(f"总字节数: {sum(frame['frame_structure']['total_frame_size'] for frame in frames)}") + + # 按操作码统计 + opcode_stats = {} + for frame in frames: + opcode = frame['frame_header']['opcode_name'] + opcode_stats[opcode] = opcode_stats.get(opcode, 0) + 1 + + print("\n操作码统计:") + for opcode, count in opcode_stats.items(): + print(f" {opcode}: {count} 帧") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/test_ws_parser/websocket_frames_analysis.json b/test_ws_parser/websocket_frames_analysis.json new file mode 100644 index 000000000..52b33eb0f --- /dev/null +++ b/test_ws_parser/websocket_frames_analysis.json @@ -0,0 +1,5605 @@ +{ + "analysis_summary": { + "total_frames": 33, + "total_bytes": 2361 + }, + "frames": [ + { + "frame_index": 0, + "offset_in_stream": 0, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 5, + "opcode_name": "UNKNOWN(0x05)", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 EF BC 8C 22 2C 22 74 61 73 6B 5F 69 64", + "bytes": [ + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 239, + 188, + 140, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100 + ] + }, + "payload": { + "hex": "3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 EF BC 8C 22 2C 22 74 61 73 6B 5F 69 64", + "bytes": [ + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 239, + 188, + 140, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100 + ], + "utf8": ":\"middle\",\"content\":\",\",\"task_id", + "json": null + } + }, + { + "frame_index": 1, + "offset_in_stream": 36, + "frame_header": { + "fin": 0, + "rsv": 2, + "opcode": 2, + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 58 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 60, + "payload_size": 58 + }, + "raw_data": { + "hex": "22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD", + "bytes": [ + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 189 + ] + }, + "payload": { + "hex": "22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD", + "bytes": [ + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 189 + ], + "utf8": "\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"", + "json": null + } + }, + { + "frame_index": 2, + "offset_in_stream": 96, + "frame_header": { + "fin": 1, + "rsv": 2, + "opcode": 0, + "opcode_name": "CONTINUATION", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A", + "bytes": [ + 160, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58 + ] + }, + "payload": { + "hex": "2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A", + "bytes": [ + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58 + ], + "utf8": ",\"task_id\":\"\",\"reasoning_content\":", + "json": null + } + }, + { + "frame_index": 3, + "offset_in_stream": 132, + "frame_header": { + "fin": 0, + "rsv": 2, + "opcode": 2, + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 B8 80", + "bytes": [ + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 184, + 128 + ] + }, + "payload": { + "hex": "7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 B8 80", + "bytes": [ + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 184, + 128 + ], + "utf8": "}H{\"type\":\"middle\",\"content\":\"一", + "json": null + } + }, + { + "frame_index": 4, + "offset_in_stream": 168, + "frame_header": { + "fin": 1, + "rsv": 6, + "opcode": 5, + "opcode_name": "UNKNOWN(0x05)", + "mask": 1, + "payload_length": 46 + }, + "frame_structure": { + "header_size": 6, + "total_frame_size": 52, + "payload_size": 46 + }, + "raw_data": { + "hex": "E5 AE 9A 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22", + "bytes": [ + 229, + 174, + 154, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34 + ] + }, + "payload": { + "hex": "EE 43 5F 49 C5 4B 48 00 A0 00 0E 0E B8 50 49 43 E9 4D 42 4B F4 45 73 41 F5 4C 58 47 F4 56 0E 18 B8 00 51 A0 DF 59 0E 56 E3 52 49 00 A0 00", + "bytes": [ + 238, + 67, + 95, + 73, + 197, + 75, + 72, + 0, + 160, + 0, + 14, + 14, + 184, + 80, + 73, + 67, + 233, + 77, + 66, + 75, + 244, + 69, + 115, + 65, + 245, + 76, + 88, + 71, + 244, + 86, + 14, + 24, + 184, + 0, + 81, + 160, + 223, + 89, + 14, + 86, + 227, + 82, + 73, + 0, + 160, + 0 + ], + "utf8": "C_IKH\u0000\u0000\u000e\u000ePICMBKEsALXGV\u000e\u0018\u0000QY\u000eVRI\u0000\u0000", + "json": null + } + }, + { + "frame_index": 5, + "offset_in_stream": 220, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 13, + "opcode_name": "UNKNOWN(0x0D)", + "mask": 0, + "payload_length": 105 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 107, + "payload_size": 105 + }, + "raw_data": { + "hex": "6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BE 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22", + "bytes": [ + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 230, + 156, + 137, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 190, + 136, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34 + ] + }, + "payload": { + "hex": "64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BE 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22", + "bytes": [ + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 230, + 156, + 137, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 190, + 136, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34 + ], + "utf8": "ddle\",\"content\":\"有\",\"task_id\":\"\",\"reasoning_content\":\"\"}H{\"type\":\"middle\",\"content\":\"很\",\"task_id\":\"\"", + "json": null + } + }, + { + "frame_index": 6, + "offset_in_stream": 327, + "frame_header": { + "fin": 0, + "rsv": 2, + "opcode": 12, + "opcode_name": "UNKNOWN(0x0C)", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D", + "bytes": [ + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109 + ] + }, + "payload": { + "hex": "72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D", + "bytes": [ + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109 + ], + "utf8": "reasoning_content\":\"\"}H{\"type\":\"m", + "json": null + } + }, + { + "frame_index": 7, + "offset_in_stream": 363, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 9, + "opcode_name": "PING", + "mask": 0, + "payload_length": 100 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 102, + "payload_size": 100 + }, + "raw_data": { + "hex": "69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 84 89 E5 BF AB 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B", + "bytes": [ + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 230, + 132, + 137, + 229, + 191, + 171, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 231, + 154, + 132, + 34, + 44, + 34, + 116, + 97, + 115, + 107 + ] + }, + "payload": { + "hex": "64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 84 89 E5 BF AB 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B", + "bytes": [ + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 230, + 132, + 137, + 229, + 191, + 171, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 231, + 154, + 132, + 34, + 44, + 34, + 116, + 97, + 115, + 107 + ], + "utf8": "dle\",\"content\":\"愉快\",\"task_id\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"的\",\"task", + "json": null + } + }, + { + "frame_index": 8, + "offset_in_stream": 465, + "frame_header": { + "fin": 0, + "rsv": 5, + "opcode": 15, + "opcode_name": "UNKNOWN(0x0F)", + "mask": 0, + "payload_length": 105 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 107, + "payload_size": 105 + }, + "raw_data": { + "hex": "5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BF 83 E6 83 85 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45", + "bytes": [ + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 191, + 131, + 230, + 131, + 133, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69 + ] + }, + "payload": { + "hex": "64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BF 83 E6 83 85 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45", + "bytes": [ + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 191, + 131, + 230, + 131, + 133, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69 + ], + "utf8": "d\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"心情\",\"task_id\":\"\",\"reasoning_content\":\"\"}E", + "json": null + } + }, + { + "frame_index": 9, + "offset_in_stream": 572, + "frame_header": { + "fin": 0, + "rsv": 7, + "opcode": 11, + "opcode_name": "UNKNOWN(0x0B)", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 90 A7 22 2C 22 74 61", + "bytes": [ + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 144, + 167, + 34, + 44, + 34, + 116, + 97 + ] + }, + "payload": { + "hex": "74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 90 A7 22 2C 22 74 61", + "bytes": [ + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 144, + 167, + 34, + 44, + 34, + 116, + 97 + ], + "utf8": "type\":\"middle\",\"content\":\"吧\",\"ta", + "json": null + } + }, + { + "frame_index": 10, + "offset_in_stream": 608, + "frame_header": { + "fin": 0, + "rsv": 7, + "opcode": 3, + "opcode_name": "UNKNOWN(0x03)", + "mask": 0, + "payload_length": 107 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 109, + "payload_size": 107 + }, + "raw_data": { + "hex": "73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65", + "bytes": [ + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 66, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 70, + 123, + 34, + 116, + 121, + 112, + 101 + ] + }, + "payload": { + "hex": "5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65", + "bytes": [ + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 66, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 70, + 123, + 34, + 116, + 121, + 112, + 101 + ], + "utf8": "_id\":\"\",\"reasoning_content\":\"\"}B{\"type\":\"middle\",\"content\":\"\",\"task_id\":\"\",\"reasoning_content\":\"\"}F{\"type", + "json": null + } + }, + { + "frame_index": 11, + "offset_in_stream": 717, + "frame_header": { + "fin": 0, + "rsv": 2, + "opcode": 2, + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 58 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 60, + "payload_size": 58 + }, + "raw_data": { + "hex": "22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F 98 98 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22", + "bytes": [ + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 240, + 159, + 152, + 152, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34 + ] + }, + "payload": { + "hex": "22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F 98 98 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22", + "bytes": [ + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 240, + 159, + 152, + 152, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34 + ], + "utf8": "\"middle\",\"content\":\"😘\",\"task_id\":\"\",\"reasoning_content\"", + "json": null + } + }, + { + "frame_index": 12, + "offset_in_stream": 777, + "frame_header": { + "fin": 0, + "rsv": 3, + "opcode": 10, + "opcode_name": "PONG", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "3A 22 22 7D 82 43 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 20 22", + "bytes": [ + 58, + 34, + 34, + 125, + 130, + 67, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 32, + 34 + ] + }, + "payload": { + "hex": "22 7D 82 43 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 20 22", + "bytes": [ + 34, + 125, + 130, + 67, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 32, + 34 + ], + "utf8": "\"}C{\"type\":\"middle\",\"content\":\" \"", + "json": null + } + }, + { + "frame_index": 13, + "offset_in_stream": 813, + "frame_header": { + "fin": 0, + "rsv": 2, + "opcode": 12, + "opcode_name": "UNKNOWN(0x0C)", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22", + "bytes": [ + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34 + ] + }, + "payload": { + "hex": "74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22", + "bytes": [ + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34 + ], + "utf8": "task_id\":\"\",\"reasoning_content\":\"\"", + "json": null + } + }, + { + "frame_index": 14, + "offset_in_stream": 849, + "frame_header": { + "fin": 0, + "rsv": 7, + "opcode": 13, + "opcode_name": "UNKNOWN(0x0D)", + "mask": 1, + "payload_length": 2 + }, + "frame_structure": { + "header_size": 6, + "total_frame_size": 8, + "payload_size": 2 + }, + "raw_data": { + "hex": "7D 82 45 7B 22 74 79 70", + "bytes": [ + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112 + ] + }, + "payload": { + "hex": "3C 0B", + "bytes": [ + 60, + 11 + ], + "utf8": "<\u000b", + "json": null + } + }, + { + "frame_index": 15, + "offset_in_stream": 857, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 5, + "opcode_name": "UNKNOWN(0x05)", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64", + "bytes": [ + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 189, + 160, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100 + ] + }, + "payload": { + "hex": "3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64", + "bytes": [ + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 189, + 160, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100 + ], + "utf8": ":\"middle\",\"content\":\"你\",\"task_id", + "json": null + } + }, + { + "frame_index": 16, + "offset_in_stream": 893, + "frame_header": { + "fin": 0, + "rsv": 2, + "opcode": 2, + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 58 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 60, + "payload_size": 58 + }, + "raw_data": { + "hex": "22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 8F", + "bytes": [ + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 143 + ] + }, + "payload": { + "hex": "22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 8F", + "bytes": [ + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 143 + ], + "utf8": "\"\",\"reasoning_content\":\"\"}H{\"type\":\"middle\",\"content\":\"", + "json": null + } + }, + { + "frame_index": 17, + "offset_in_stream": 953, + "frame_header": { + "fin": 1, + "rsv": 2, + "opcode": 15, + "opcode_name": "UNKNOWN(0x0F)", + "mask": 1, + "payload_length": 100 + }, + "frame_structure": { + "header_size": 6, + "total_frame_size": 106, + "payload_size": 100 + }, + "raw_data": { + "hex": "AF E4 BB A5 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 92 8C 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65", + "bytes": [ + 175, + 228, + 187, + 165, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 146, + 140, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101 + ] + }, + "payload": { + "hex": "99 D1 43 5F D0 FA 4B 48 99 9F 00 0E 97 87 50 49 DA D6 4D 42 D2 CB 45 73 D8 CA 4C 58 DE CB 56 0E 81 87 00 51 39 E0 59 0E CF DC 52 49 99 9F 00 41 D2 C1 46 40 DE 87 0E 0E D8 CA 4C 58 DE CB 56 0E 81 87 C7 BE 37 87 0E 0E CF C4 51 47 E4 CC 46 0E 81 87 00 00 99 D7 47 4D C8 CA 4C 45 D5 C2 7D 4F D4 CB 56 49", + "bytes": [ + 153, + 209, + 67, + 95, + 208, + 250, + 75, + 72, + 153, + 159, + 0, + 14, + 151, + 135, + 80, + 73, + 218, + 214, + 77, + 66, + 210, + 203, + 69, + 115, + 216, + 202, + 76, + 88, + 222, + 203, + 86, + 14, + 129, + 135, + 0, + 81, + 57, + 224, + 89, + 14, + 207, + 220, + 82, + 73, + 153, + 159, + 0, + 65, + 210, + 193, + 70, + 64, + 222, + 135, + 14, + 14, + 216, + 202, + 76, + 88, + 222, + 203, + 86, + 14, + 129, + 135, + 199, + 190, + 55, + 135, + 14, + 14, + 207, + 196, + 81, + 71, + 228, + 204, + 70, + 14, + 129, + 135, + 0, + 0, + 153, + 215, + 71, + 77, + 200, + 202, + 76, + 69, + 213, + 194, + 125, + 79, + 212, + 203, + 86, + 73 + ], + "utf8": "C_KH\u0000\u000ePIMBEsLXV\u000e\u0000Q9Y\u000eRI\u0000AF@އ\u000e\u000eLXV\u000eǾ7\u000e\u000eQGF\u000e\u0000\u0000GMLE}OVI", + "json": null + } + }, + { + "frame_index": 18, + "offset_in_stream": 1059, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 14, + "opcode_name": "UNKNOWN(0x0E)", + "mask": 0, + "payload_length": 116 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 118, + "payload_size": 116 + }, + "raw_data": { + "hex": "6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 88 91 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74", + "bytes": [ + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 230, + 136, + 145, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 232, + 175, + 180, + 232, + 175, + 180, + 34, + 44, + 34, + 116 + ] + }, + "payload": { + "hex": "22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 88 91 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74", + "bytes": [ + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 230, + 136, + 145, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 232, + 175, + 180, + 232, + 175, + 180, + 34, + 44, + 34, + 116 + ], + "utf8": "\":\"\"}E{\"type\":\"middle\",\"content\":\"我\",\"task_id\":\"\",\"reasoning_content\":\"\"}H{\"type\":\"middle\",\"content\":\"说说\",\"t", + "json": null + } + }, + { + "frame_index": 19, + "offset_in_stream": 1177, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 1, + "opcode_name": "TEXT", + "mask": 0, + "payload_length": 115 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 117, + "payload_size": 115 + }, + "raw_data": { + "hex": "61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D", + "bytes": [ + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 230, + 156, + 137, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109 + ] + }, + "payload": { + "hex": "6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D", + "bytes": [ + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 230, + 156, + 137, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 72, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109 + ], + "utf8": "k_id\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"有\",\"task_id\":\"\",\"reasoning_content\":\"\"}H{\"type\":\"m", + "json": null + } + }, + { + "frame_index": 20, + "offset_in_stream": 1294, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 9, + "opcode_name": "PING", + "mask": 0, + "payload_length": 100 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 102, + "payload_size": 100 + }, + "raw_data": { + "hex": "69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BB 80 E4 B9 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BA 8B 22 2C 22 74 61 73 6B", + "bytes": [ + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 187, + 128, + 228, + 185, + 136, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 186, + 139, + 34, + 44, + 34, + 116, + 97, + 115, + 107 + ] + }, + "payload": { + "hex": "64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BB 80 E4 B9 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BA 8B 22 2C 22 74 61 73 6B", + "bytes": [ + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 187, + 128, + 228, + 185, + 136, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 228, + 186, + 139, + 34, + 44, + 34, + 116, + 97, + 115, + 107 + ], + "utf8": "dle\",\"content\":\"什么\",\"task_id\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"事\",\"task", + "json": null + } + }, + { + "frame_index": 21, + "offset_in_stream": 1396, + "frame_header": { + "fin": 0, + "rsv": 5, + "opcode": 15, + "opcode_name": "UNKNOWN(0x0F)", + "mask": 0, + "payload_length": 105 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 107, + "payload_size": 105 + }, + "raw_data": { + "hex": "5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 80 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74", + "bytes": [ + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 145, + 128, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 66, + 123, + 34, + 116 + ] + }, + "payload": { + "hex": "64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 80 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74", + "bytes": [ + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 69, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 229, + 145, + 128, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 66, + 123, + 34, + 116 + ], + "utf8": "d\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"呀\",\"task_id\":\"\",\"reasoning_content\":\"\"}B{\"t", + "json": null + } + }, + { + "frame_index": 22, + "offset_in_stream": 1503, + "frame_header": { + "fin": 0, + "rsv": 7, + "opcode": 9, + "opcode_name": "PING", + "mask": 0, + "payload_length": 112 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 114, + "payload_size": 112 + }, + "raw_data": { + "hex": "79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F A7 90 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72", + "bytes": [ + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 70, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 240, + 159, + 167, + 144, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114 + ] + }, + "payload": { + "hex": "65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F A7 90 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72", + "bytes": [ + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 70, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 240, + 159, + 167, + 144, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114 + ], + "utf8": "e\":\"middle\",\"content\":\"\",\"task_id\":\"\",\"reasoning_content\":\"\"}F{\"type\":\"middle\",\"content\":\"🧐\",\"task_id\":\"\",\"r", + "json": null + } + }, + { + "frame_index": 23, + "offset_in_stream": 1617, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 5, + "opcode_name": "UNKNOWN(0x05)", + "mask": 0, + "payload_length": 97 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 99, + "payload_size": 97 + }, + "raw_data": { + "hex": "65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 41 7B 22 74 79 70 65 22 3A", + "bytes": [ + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 66, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 65, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58 + ] + }, + "payload": { + "hex": "73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 41 7B 22 74 79 70 65 22 3A", + "bytes": [ + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 66, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58, + 34, + 109, + 105, + 100, + 100, + 108, + 101, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 130, + 65, + 123, + 34, + 116, + 121, + 112, + 101, + 34, + 58 + ], + "utf8": "soning_content\":\"\"}B{\"type\":\"middle\",\"content\":\"\",\"task_id\":\"\",\"reasoning_content\":\"\"}A{\"type\":", + "json": null + } + }, + { + "frame_index": 24, + "offset_in_stream": 1716, + "frame_header": { + "fin": 0, + "rsv": 2, + "opcode": 2, + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 101 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 103, + "payload_size": 101 + }, + "raw_data": { + "hex": "22 65 6E 64 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 6E 75 6C 6C 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 81 7E 00 BB 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69", + "bytes": [ + 34, + 101, + 110, + 100, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 110, + 117, + 108, + 108, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 129, + 126, + 0, + 187, + 123, + 34, + 115, + 116, + 97, + 116, + 117, + 115, + 34, + 58, + 50, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 44, + 34, + 109, + 115, + 103, + 34, + 58, + 34, + 115, + 117, + 99, + 99, + 101, + 115, + 115, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105 + ] + }, + "payload": { + "hex": "6E 64 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 6E 75 6C 6C 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 81 7E 00 BB 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69", + "bytes": [ + 110, + 100, + 34, + 44, + 34, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 110, + 117, + 108, + 108, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 114, + 101, + 97, + 115, + 111, + 110, + 105, + 110, + 103, + 95, + 99, + 111, + 110, + 116, + 101, + 110, + 116, + 34, + 58, + 34, + 34, + 125, + 129, + 126, + 0, + 187, + 123, + 34, + 115, + 116, + 97, + 116, + 117, + 115, + 34, + 58, + 50, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 44, + 34, + 109, + 115, + 103, + 34, + 58, + 34, + 115, + 117, + 99, + 99, + 101, + 115, + 115, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105 + ], + "utf8": "nd\",\"content\":null,\"task_id\":\"\",\"reasoning_content\":\"\"}~\u0000{\"status\":20000000,\"msg\":\"success\",\"task_i", + "json": null + } + }, + { + "frame_index": 25, + "offset_in_stream": 1819, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 4, + "opcode_name": "UNKNOWN(0x04)", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 39 34 33 33 37 62 64 65 33 37", + "bytes": [ + 100, + 34, + 58, + 34, + 97, + 49, + 97, + 101, + 101, + 50, + 100, + 55, + 53, + 56, + 97, + 54, + 100, + 51, + 57, + 51, + 51, + 97, + 50, + 52, + 54, + 54, + 57, + 52, + 51, + 51, + 55, + 98, + 100, + 101, + 51, + 55 + ] + }, + "payload": { + "hex": "3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 39 34 33 33 37 62 64 65 33 37", + "bytes": [ + 58, + 34, + 97, + 49, + 97, + 101, + 101, + 50, + 100, + 55, + 53, + 56, + 97, + 54, + 100, + 51, + 57, + 51, + 51, + 97, + 50, + 52, + 54, + 54, + 57, + 52, + 51, + 51, + 55, + 98, + 100, + 101, + 51, + 55 + ], + "utf8": ":\"a1aee2d758a6d3933a246694337bde37", + "json": null + } + }, + { + "frame_index": 26, + "offset_in_stream": 1855, + "frame_header": { + "fin": 0, + "rsv": 2, + "opcode": 2, + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 44 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 46, + "payload_size": 44 + }, + "raw_data": { + "hex": "22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E4 BB 96 E4 BD A0", + "bytes": [ + 34, + 44, + 34, + 101, + 118, + 101, + 110, + 116, + 34, + 58, + 34, + 67, + 104, + 97, + 110, + 103, + 101, + 100, + 34, + 44, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 123, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 34, + 228, + 187, + 150, + 228, + 189, + 160 + ] + }, + "payload": { + "hex": "22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E4 BB 96 E4 BD A0", + "bytes": [ + 34, + 101, + 118, + 101, + 110, + 116, + 34, + 58, + 34, + 67, + 104, + 97, + 110, + 103, + 101, + 100, + 34, + 44, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 123, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 34, + 228, + 187, + 150, + 228, + 189, + 160 + ], + "utf8": "\"event\":\"Changed\",\"result\":{\"result\":\"他你", + "json": null + } + }, + { + "frame_index": 27, + "offset_in_stream": 1901, + "frame_header": { + "fin": 0, + "rsv": 2, + "opcode": 2, + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 44 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 46, + "payload_size": 44 + }, + "raw_data": { + "hex": "22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22", + "bytes": [ + 34, + 44, + 34, + 105, + 115, + 95, + 101, + 110, + 100, + 34, + 58, + 102, + 97, + 108, + 115, + 101, + 44, + 34, + 115, + 101, + 110, + 116, + 101, + 110, + 99, + 101, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 115, + 116, + 97, + 114, + 116, + 95, + 116, + 105, + 109, + 101, + 34 + ] + }, + "payload": { + "hex": "22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22", + "bytes": [ + 34, + 105, + 115, + 95, + 101, + 110, + 100, + 34, + 58, + 102, + 97, + 108, + 115, + 101, + 44, + 34, + 115, + 101, + 110, + 116, + 101, + 110, + 99, + 101, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 115, + 116, + 97, + 114, + 116, + 95, + 116, + 105, + 109, + 101, + 34 + ], + "utf8": "\"is_end\":false,\"sentence_id\":\"\",\"start_time\"", + "json": null + } + }, + { + "frame_index": 28, + "offset_in_stream": 1947, + "frame_header": { + "fin": 0, + "rsv": 3, + "opcode": 10, + "opcode_name": "PONG", + "mask": 0, + "payload_length": 48 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 50, + "payload_size": 48 + }, + "raw_data": { + "hex": "3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 C4 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63", + "bytes": [ + 58, + 48, + 44, + 34, + 101, + 110, + 100, + 95, + 116, + 105, + 109, + 101, + 34, + 58, + 48, + 125, + 125, + 129, + 126, + 0, + 196, + 123, + 34, + 115, + 116, + 97, + 116, + 117, + 115, + 34, + 58, + 50, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 44, + 34, + 109, + 115, + 103, + 34, + 58, + 34, + 115, + 117, + 99 + ] + }, + "payload": { + "hex": "2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 C4 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63", + "bytes": [ + 44, + 34, + 101, + 110, + 100, + 95, + 116, + 105, + 109, + 101, + 34, + 58, + 48, + 125, + 125, + 129, + 126, + 0, + 196, + 123, + 34, + 115, + 116, + 97, + 116, + 117, + 115, + 34, + 58, + 50, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 44, + 34, + 109, + 115, + 103, + 34, + 58, + 34, + 115, + 117, + 99 + ], + "utf8": ",\"end_time\":0}}~\u0000{\"status\":20000000,\"msg\":\"suc", + "json": null + } + }, + { + "frame_index": 29, + "offset_in_stream": 1997, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 3, + "opcode_name": "UNKNOWN(0x03)", + "mask": 0, + "payload_length": 101 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 103, + "payload_size": 101 + }, + "raw_data": { + "hex": "63 65 73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C", + "bytes": [ + 99, + 101, + 115, + 115, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 97, + 49, + 97, + 101, + 101, + 50, + 100, + 55, + 53, + 56, + 97, + 54, + 100, + 51, + 57, + 51, + 51, + 97, + 50, + 52, + 54, + 54, + 105, + 52, + 51, + 51, + 55, + 98, + 100, + 101, + 51, + 55, + 34, + 44, + 34, + 101, + 118, + 101, + 110, + 116, + 34, + 58, + 34, + 67, + 104, + 97, + 110, + 103, + 101, + 100, + 34, + 44, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 123, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 34, + 231, + 156, + 139, + 232, + 181, + 183, + 230, + 157, + 165, + 231, + 142, + 176, + 229, + 156 + ] + }, + "payload": { + "hex": "73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C", + "bytes": [ + 115, + 115, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 97, + 49, + 97, + 101, + 101, + 50, + 100, + 55, + 53, + 56, + 97, + 54, + 100, + 51, + 57, + 51, + 51, + 97, + 50, + 52, + 54, + 54, + 105, + 52, + 51, + 51, + 55, + 98, + 100, + 101, + 51, + 55, + 34, + 44, + 34, + 101, + 118, + 101, + 110, + 116, + 34, + 58, + 34, + 67, + 104, + 97, + 110, + 103, + 101, + 100, + 34, + 44, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 123, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 34, + 231, + 156, + 139, + 232, + 181, + 183, + 230, + 157, + 165, + 231, + 142, + 176, + 229, + 156 + ], + "utf8": "ss\",\"task_id\":\"a1aee2d758a6d3933a2466i4337bde37\",\"event\":\"Changed\",\"result\":{\"result\":\"看起来现", + "json": null + } + }, + { + "frame_index": 30, + "offset_in_stream": 2100, + "frame_header": { + "fin": 1, + "rsv": 2, + "opcode": 8, + "opcode_name": "CLOSE", + "mask": 1, + "payload_length": 102 + }, + "frame_structure": { + "header_size": 6, + "total_frame_size": 108, + "payload_size": 102 + }, + "raw_data": { + "hex": "A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 CD 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65", + "bytes": [ + 168, + 230, + 152, + 175, + 230, + 173, + 163, + 229, + 184, + 184, + 34, + 44, + 34, + 105, + 115, + 95, + 101, + 110, + 100, + 34, + 58, + 102, + 97, + 108, + 115, + 101, + 44, + 34, + 115, + 101, + 110, + 116, + 101, + 110, + 99, + 101, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 115, + 116, + 97, + 114, + 116, + 95, + 116, + 105, + 109, + 101, + 34, + 58, + 48, + 44, + 34, + 101, + 110, + 100, + 95, + 116, + 105, + 109, + 101, + 34, + 58, + 48, + 125, + 125, + 129, + 126, + 0, + 205, + 123, + 34, + 115, + 116, + 97, + 116, + 117, + 115, + 34, + 58, + 50, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 44, + 34, + 109, + 115, + 103, + 34, + 58, + 34, + 115, + 117, + 99, + 99, + 101 + ] + }, + "payload": { + "hex": "3B 4A 5E 15 BA 83 C4 C4 EB F0 83 C3 FC 8D DC CB F9 C3 95 C8 B4 8D 95 C8 F6 DB 83 C3 FB CA B9 C4 FC 8D DC 8F BA 83 C4 DE EC CE 94 D9 C7 DB 8F C0 FD 8D DC 9D B4 8D 83 C3 FC F0 92 C4 F5 CA C4 97 A8 D2 9B 2C E6 AF 2B D6 BA DC 92 CC EC DA 95 8F A2 9D D6 9D A8 9F D6 9D A8 83 C4 C0 EB C8 C4 97 BA DC 93 CE FB CA", + "bytes": [ + 59, + 74, + 94, + 21, + 186, + 131, + 196, + 196, + 235, + 240, + 131, + 195, + 252, + 141, + 220, + 203, + 249, + 195, + 149, + 200, + 180, + 141, + 149, + 200, + 246, + 219, + 131, + 195, + 251, + 202, + 185, + 196, + 252, + 141, + 220, + 143, + 186, + 131, + 196, + 222, + 236, + 206, + 148, + 217, + 199, + 219, + 143, + 192, + 253, + 141, + 220, + 157, + 180, + 141, + 131, + 195, + 252, + 240, + 146, + 196, + 245, + 202, + 196, + 151, + 168, + 210, + 155, + 44, + 230, + 175, + 43, + 214, + 186, + 220, + 146, + 204, + 236, + 218, + 149, + 143, + 162, + 157, + 214, + 157, + 168, + 159, + 214, + 157, + 168, + 131, + 196, + 192, + 235, + 200, + 196, + 151, + 186, + 220, + 147, + 206, + 251, + 202 + ], + "utf8": ";J^\u0015Õȴۃʹ܏Δۏܝėқ,+ֺܒڕ֝֝ėܓ", + "json": null + } + }, + { + "frame_index": 31, + "offset_in_stream": 2208, + "frame_header": { + "fin": 0, + "rsv": 7, + "opcode": 3, + "opcode_name": "UNKNOWN(0x03)", + "mask": 0, + "payload_length": 115 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 117, + "payload_size": 115 + }, + "raw_data": { + "hex": "73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F", + "bytes": [ + 115, + 115, + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 97, + 49, + 97, + 101, + 101, + 50, + 100, + 55, + 53, + 56, + 97, + 54, + 100, + 51, + 57, + 51, + 51, + 97, + 50, + 52, + 54, + 54, + 105, + 52, + 51, + 51, + 55, + 98, + 100, + 101, + 51, + 55, + 34, + 44, + 34, + 101, + 118, + 101, + 110, + 116, + 34, + 58, + 34, + 67, + 104, + 97, + 110, + 103, + 101, + 100, + 34, + 44, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 123, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 34, + 231, + 156, + 139, + 232, + 181, + 183, + 230, + 157, + 165, + 231, + 142, + 176, + 229, + 156, + 168, + 230, + 152, + 175, + 230, + 173, + 163, + 229, + 184, + 184, + 34, + 44, + 34, + 105, + 115, + 95 + ] + }, + "payload": { + "hex": "22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F", + "bytes": [ + 34, + 44, + 34, + 116, + 97, + 115, + 107, + 95, + 105, + 100, + 34, + 58, + 34, + 97, + 49, + 97, + 101, + 101, + 50, + 100, + 55, + 53, + 56, + 97, + 54, + 100, + 51, + 57, + 51, + 51, + 97, + 50, + 52, + 54, + 54, + 105, + 52, + 51, + 51, + 55, + 98, + 100, + 101, + 51, + 55, + 34, + 44, + 34, + 101, + 118, + 101, + 110, + 116, + 34, + 58, + 34, + 67, + 104, + 97, + 110, + 103, + 101, + 100, + 34, + 44, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 123, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 34, + 231, + 156, + 139, + 232, + 181, + 183, + 230, + 157, + 165, + 231, + 142, + 176, + 229, + 156, + 168, + 230, + 152, + 175, + 230, + 173, + 163, + 229, + 184, + 184, + 34, + 44, + 34, + 105, + 115, + 95 + ], + "utf8": "\",\"task_id\":\"a1aee2d758a6d3933a2466i4337bde37\",\"event\":\"Changed\",\"result\":{\"result\":\"看起来现在是正常\",\"is_", + "json": null + } + }, + { + "frame_index": 32, + "offset_in_stream": 2327, + "frame_header": { + "fin": 0, + "rsv": 6, + "opcode": 4, + "opcode_name": "UNKNOWN(0x04)", + "mask": 0, + "payload_length": 34 + }, + "frame_structure": { + "header_size": 2, + "total_frame_size": 36, + "payload_size": 34 + }, + "raw_data": { + "hex": "64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D", + "bytes": [ + 100, + 34, + 58, + 102, + 97, + 108, + 115, + 101, + 44, + 34, + 115, + 101, + 110, + 116, + 101, + 110, + 99, + 101, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 115, + 116, + 97, + 114, + 116, + 95, + 116, + 105, + 109 + ] + }, + "payload": { + "hex": "3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D", + "bytes": [ + 58, + 102, + 97, + 108, + 115, + 101, + 44, + 34, + 115, + 101, + 110, + 116, + 101, + 110, + 99, + 101, + 95, + 105, + 100, + 34, + 58, + 34, + 34, + 44, + 34, + 115, + 116, + 97, + 114, + 116, + 95, + 116, + 105, + 109 + ], + "utf8": ":false,\"sentence_id\":\"\",\"start_tim", + "json": null + } + } + ] +} \ No newline at end of file diff --git a/test_ws_parser/websocket_parser_standalone.cpp b/test_ws_parser/websocket_parser_standalone.cpp new file mode 100644 index 000000000..c02304b2f --- /dev/null +++ b/test_ws_parser/websocket_parser_standalone.cpp @@ -0,0 +1,989 @@ +#include +#include +#include +#include + +// 控制日志输出的宏 +#define ENABLE_DEBUG_LOG 1 // 设置为0可以关闭所有调试输出 + +#if ENABLE_DEBUG_LOG +#define WS_LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__) +#define WS_LOGI(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__) +#define WS_LOGD(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__) +#define WS_LOGE(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__) +#else +#define WS_LOG(fmt, ...) +#define WS_LOGI(fmt, ...) +#define WS_LOGD(fmt, ...) +#define WS_LOGE(fmt, ...) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * WebSocket协议解析器 (RFC 6455) + */ + +// WebSocket帧类型枚举 +typedef enum { + WS_CONTINUATION = 0x0, + WS_TEXT = 0x1, + WS_BINARY = 0x2, + WS_CLOSE = 0x8, + WS_PING = 0x9, + WS_PONG = 0xA +} ws_opcode_t; + +// WebSocket解析状态 +typedef enum { + WS_STATE_START, + WS_STATE_READ_HEADER1, + WS_STATE_READ_HEADER2, + WS_STATE_READ_PAYLOAD_LEN, + WS_STATE_READ_MASK, + WS_STATE_READ_PAYLOAD, + WS_STATE_COMPLETE, + WS_STATE_ERROR +} ws_parse_state_t; + +// WebSocket帧头部信息 +typedef struct { + uint8_t fin; // 帧结束标志 + uint8_t rsv1; // 保留位1 + uint8_t rsv2; // 保留位2 + uint8_t rsv3; // 保留位3 + ws_opcode_t opcode; // 操作码 + uint8_t mask; // 掩码标志 + uint64_t payload_len; // 负载长度 + uint8_t mask_key[4]; // 掩码密钥 +} ws_header_t; + +// WebSocket解析上下文 +typedef struct { + ws_parse_state_t state; // 当前解析状态 + ws_header_t header; // 解析出的头部信息 + uint8_t* buffer; // 数据缓存 + size_t buffer_pos; // 缓存当前位置 + size_t payload_remaining; // 剩余需要读取的负载长度 + size_t mask_pos; // 掩码读取位置 +} ws_parser_t; + +// 全局动态分配缓存(1024字节) +uint8_t* g_ws_buffer = NULL; +#define WS_BUFFER_SIZE 1024 + +// WebSocket协议长度限制配置 +#define WS_MAX_PAYLOAD_LEN_DEFAULT 65535 // 默认最大负载长度(16位) +#define WS_MAX_PAYLOAD_LEN_MAX 1048576 // 最大允许的负载长度(1MB) +#define WS_CONTROL_FRAME_MAX_LEN 125 // 控制帧最大负载长度(RFC 6455规定) + +static int g_parser_count = 0; // 解析器实例计数 +static uint64_t g_max_payload_len = WS_MAX_PAYLOAD_LEN_DEFAULT; // 全局最大负载长度配置 + +// 初始化WebSocket解析器 +ws_parser_t* ws_parser_init() { + WS_LOGI("WS: Initializing WebSocket parser"); + + ws_parser_t* parser = (ws_parser_t*)malloc(sizeof(ws_parser_t)); + if (!parser) { + WS_LOGE("WS: Failed to allocate memory for parser"); + return NULL; + } + + // 初始化全局缓存 + if (!g_ws_buffer) { + WS_LOGI("WS: Allocating global buffer (%d bytes)", WS_BUFFER_SIZE); + g_ws_buffer = (uint8_t*)malloc(WS_BUFFER_SIZE); + if (!g_ws_buffer) { + WS_LOGE("WS: Failed to allocate global buffer"); + free(parser); + return NULL; + } + } + + g_parser_count++; + WS_LOGI("WS: Parser count: %d", g_parser_count); + + // 初始化解析器状态 + parser->state = WS_STATE_START; + parser->buffer = g_ws_buffer; + parser->buffer_pos = 0; + parser->payload_remaining = 0; + parser->mask_pos = 0; + memset(&parser->header, 0, sizeof(ws_header_t)); + + WS_LOGI("WS: Parser initialized successfully"); + return parser; +} + +// 重置解析器状态 +void ws_parser_reset(ws_parser_t* parser) { + if (!parser) return; + + parser->state = WS_STATE_START; + parser->buffer_pos = 0; + parser->payload_remaining = 0; + parser->mask_pos = 0; + memset(&parser->header, 0, sizeof(ws_header_t)); +} + +// 应用掩码解码 +void apply_mask(uint8_t* data, size_t len, const uint8_t* mask_key, size_t offset) { + for (size_t i = 0; i < len; i++) { + data[i] ^= mask_key[(offset + i) % 4]; + } +} + +// 验证控制帧长度 +int validate_control_frame_length(ws_opcode_t opcode, uint64_t payload_len) { + if (opcode >= WS_CLOSE && opcode <= WS_PONG) { + if (payload_len > WS_CONTROL_FRAME_MAX_LEN) { + return 0; // 控制帧长度不能超过125字节 + } + } + return 1; +} + +// 配置最大负载长度 +int ws_set_max_payload_length(uint64_t max_len) { + WS_LOGI("WS: Setting max payload length to %llu bytes", (unsigned long long)max_len); + + if (max_len > WS_MAX_PAYLOAD_LEN_MAX) { + WS_LOGE("WS: Max payload length %llu exceeds limit %llu", + (unsigned long long)max_len, (unsigned long long)WS_MAX_PAYLOAD_LEN_MAX); + return 0; // 超过最大允许值 + } + if (max_len < 1) { + WS_LOGE("WS: Invalid max payload length: %llu (must be >= 1)", (unsigned long long)max_len); + return 0; // 不能小于1字节 + } + g_max_payload_len = max_len; + WS_LOGI("WS: Max payload length set successfully"); + return 1; +} + +// 获取当前配置的最大负载长度 +uint64_t ws_get_max_payload_length(void) { + return g_max_payload_len; +} + +// 解析单个字节 +// 返回值:0-继续解析,1-解析完成一个帧,-1-错误 +int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { + if (!parser || parser->state == WS_STATE_ERROR) { + return -1; + } + + switch (parser->state) { + case WS_STATE_START: + parser->state = WS_STATE_READ_HEADER1; + // 继续执行,处理第一个字节 + + case WS_STATE_READ_HEADER1:{ + // 解析第一个头部字节 + parser->header.fin = (byte >> 7) & 0x1; + parser->header.rsv1 = (byte >> 6) & 0x1; + parser->header.rsv2 = (byte >> 5) & 0x1; + parser->header.rsv3 = (byte >> 4) & 0x1; + parser->header.opcode = (ws_opcode_t)(byte & 0x0F); + + // 检查 opcode 是否有效 + if (!((parser->header.opcode >= WS_CONTINUATION && parser->header.opcode <= WS_BINARY) || + (parser->header.opcode >= WS_CLOSE && parser->header.opcode <= WS_PONG))) { + WS_LOGE("WS: Invalid opcode: 0x%02X", parser->header.opcode); + parser->state = WS_STATE_ERROR; + return -1; + } + + // 检查RSV位是否都为0(根据RFC6455规范) + if (!(parser->header.fin == 1 && parser->header.rsv1 == 0 && parser->header.rsv2 == 0 && parser->header.rsv3 == 0)) + { + WS_LOGE("WS: Invalid RSV bits: %d%d%d", + parser->header.rsv1, parser->header.rsv2, parser->header.rsv3); + parser->state = WS_STATE_ERROR; + return -1; + } + + WS_LOGD("WS: Parse header1 - FIN:%d, RSV:%d%d%d, OPCODE:0x%02X", + parser->header.fin, parser->header.rsv1, parser->header.rsv2, parser->header.rsv3, parser->header.opcode); + + + + // 保存第一个头部字节到缓存 + if (parser->buffer_pos < WS_BUFFER_SIZE) { + parser->buffer[parser->buffer_pos++] = byte; + } else { + parser->state = WS_STATE_ERROR; + WS_LOGE("WS: Buffer overflow in header1"); + return -1; + } + + parser->state = WS_STATE_READ_HEADER2; + break; + } + + case WS_STATE_READ_HEADER2: { + // 解析第二个头部字节 + parser->header.mask = (byte >> 7) & 0x1; + uint8_t payload_len = byte & 0x7F; + + WS_LOGD("WS: Parse header2 - MASK:%d, LEN:%d", + parser->header.mask, payload_len); + + // 保存第二个头部字节到缓存 + if (parser->buffer_pos < WS_BUFFER_SIZE) { + parser->buffer[parser->buffer_pos++] = byte; + } else { + parser->state = WS_STATE_ERROR; + WS_LOGE("WS: Buffer overflow in header2"); + return -1; + } + + // 处理负载长度 + if (payload_len <= 125) { + parser->header.payload_len = payload_len; + parser->payload_remaining = payload_len; + + WS_LOGI("WS: Small payload length: %d bytes", payload_len); + + // 验证控制帧长度 + if (!validate_control_frame_length(parser->header.opcode, payload_len)) { + WS_LOGE("WS: Control frame length validation failed: opcode=0x%02X, len=%d", + parser->header.opcode, payload_len); + parser->state = WS_STATE_ERROR; + return -1; + } + + // 如果有掩码,下一步读取掩码 + if (parser->header.mask) { + parser->state = WS_STATE_READ_MASK; + } else { + // 无掩码,直接读取负载 + if (parser->payload_remaining == 0) { + parser->state = WS_STATE_COMPLETE; + return 1; + } + parser->state = WS_STATE_READ_PAYLOAD; + } + } else if (payload_len == 126) { + // 16位长度,需要再读取2个字节 + WS_LOGI("WS: Extended 16-bit payload length mode"); + parser->header.payload_len = 126; // 临时标记 + parser->payload_remaining = 2; + parser->state = WS_STATE_READ_PAYLOAD_LEN; + } else if (payload_len == 127) { + // 64位长度,需要再读取8个字节 + WS_LOGI("WS: Extended 64-bit payload length mode"); + parser->header.payload_len = 127; // 临时标记 + parser->payload_remaining = 8; + parser->state = WS_STATE_READ_PAYLOAD_LEN; + } + break; + } + + case WS_STATE_READ_PAYLOAD_LEN: { + // 保存长度字节到缓存 + // if (parser->buffer_pos < WS_BUFFER_SIZE) { + // parser->buffer_pos++; + // } else { + // parser->state = WS_STATE_ERROR; + // WS_LOGE("WS: Buffer overflow in payload length"); + // return -1; + // } + + // 累加长度数据 + static uint8_t len_bytes[8]; + + WS_LOGD("WS: Reading payload length byte: 0x%02X, remaining: %zu", + byte, parser->payload_remaining); + + if (parser->header.payload_len == 126) { + // 16位扩展长度:只需要2个字节 + if (parser->payload_remaining == 2) { + len_bytes[0] = byte; // 高字节 + } else if (parser->payload_remaining == 1) { + len_bytes[1] = byte; // 低字节 + } + + parser->payload_remaining--; + + if (parser->payload_remaining == 0) { + // 计算16位长度 + parser->header.payload_len = (len_bytes[0] << 8) | len_bytes[1]; + parser->payload_remaining = parser->header.payload_len; + + WS_LOGI("WS: 16-bit payload length: %d bytes (0x%02X%02X)", + parser->header.payload_len, len_bytes[0], len_bytes[1]); + + // 验证控制帧长度 + if (!validate_control_frame_length(parser->header.opcode, parser->header.payload_len)) { + WS_LOGE("WS: Control frame length validation failed for 16-bit length"); + parser->state = WS_STATE_ERROR; + return -1; + } + + // 检查负载长度是否合理 + if (parser->header.payload_len > g_max_payload_len) { + WS_LOGE("WS: Payload length %d exceeds maximum %llu", + parser->header.payload_len, (unsigned long long)g_max_payload_len); + parser->state = WS_STATE_ERROR; + return -1; + } + + // 检查缓存是否足够 + if (parser->buffer_pos + parser->header.payload_len > WS_BUFFER_SIZE) { + WS_LOGE("WS: Buffer overflow: current=%zu, adding=%d, max=%d", + parser->buffer_pos, parser->header.payload_len, WS_BUFFER_SIZE); + parser->state = WS_STATE_ERROR; + return -1; + } + + // 处理掩码 + if (parser->header.mask) { + WS_LOGI("WS: Moving to READ_MASK state"); + parser->state = WS_STATE_READ_MASK; + } else { + if (parser->payload_remaining == 0) { + WS_LOGI("WS: Zero payload, moving to COMPLETE state"); + parser->state = WS_STATE_COMPLETE; + return 1; + } + WS_LOGI("WS: Moving to READ_PAYLOAD state"); + parser->state = WS_STATE_READ_PAYLOAD; + } + } + } else if (parser->header.payload_len == 127) { + // 64位扩展长度:需要8个字节 + size_t byte_index = 8 - parser->payload_remaining; + len_bytes[byte_index] = byte; + + parser->payload_remaining--; + + if (parser->payload_remaining == 0) { + // 计算64位长度 + parser->header.payload_len = 0; + for (int i = 0; i < 8; i++) { + parser->header.payload_len = (parser->header.payload_len << 8) | len_bytes[i]; + } + parser->payload_remaining = parser->header.payload_len; + + WS_LOGI("WS: 64-bit payload length: %llu bytes", + (unsigned long long)parser->header.payload_len); + + // 验证控制帧长度 + if (!validate_control_frame_length(parser->header.opcode, parser->header.payload_len)) { + WS_LOGE("WS: Control frame length validation failed for 64-bit length"); + parser->state = WS_STATE_ERROR; + return -1; + } + + // 检查负载长度是否合理 + if (parser->header.payload_len > g_max_payload_len) { + WS_LOGE("WS: Payload length %llu exceeds maximum %llu", + (unsigned long long)parser->header.payload_len, (unsigned long long)g_max_payload_len); + parser->state = WS_STATE_ERROR; + return -1; + } + + // 检查缓存是否足够 + if (parser->buffer_pos + parser->header.payload_len > WS_BUFFER_SIZE) { + WS_LOGE("WS: Buffer overflow: current=%zu, adding=%llu, max=%d", + parser->buffer_pos, (unsigned long long)parser->header.payload_len, WS_BUFFER_SIZE); + parser->state = WS_STATE_ERROR; + return -1; + } + + // 处理掩码 + if (parser->header.mask) { + WS_LOGI("WS: Moving to READ_MASK state"); + parser->state = WS_STATE_READ_MASK; + return 1; + } else { + if (parser->payload_remaining == 0) { + WS_LOGI("WS: Zero payload, moving to COMPLETE state"); + parser->state = WS_STATE_COMPLETE; + return 1; + } + WS_LOGI("WS: Moving to READ_PAYLOAD state"); + parser->state = WS_STATE_READ_PAYLOAD; + } + } + } + break; + } + + case WS_STATE_READ_MASK: { + // 读取掩码密钥 + if (parser->mask_pos < 4) { + parser->header.mask_key[parser->mask_pos++] = byte; + + if (parser->mask_pos == 4) { + WS_LOGI("WS: Mask key read complete: 0x%02X%02X%02X%02X", + parser->header.mask_key[0], parser->header.mask_key[1], + parser->header.mask_key[2], parser->header.mask_key[3]); + + if (parser->payload_remaining == 0) { + parser->state = WS_STATE_COMPLETE; + return 1; + } + parser->state = WS_STATE_READ_PAYLOAD; + } + } + break; + } + + case WS_STATE_READ_PAYLOAD: { + // 读取负载数据 + if (parser->buffer_pos < WS_BUFFER_SIZE) { + parser->buffer[parser->buffer_pos++] = byte; + parser->payload_remaining--; + + if (parser->payload_remaining == 0) { + // 负载读取完成 + WS_LOGI("WS: Payload read complete (%zu bytes)", parser->header.payload_len); + + // 如果有掩码,应用掩码解码 + if (parser->header.mask) { + // 计算负载在缓存中的起始位置 + size_t payload_start = parser->buffer_pos - parser->header.payload_len; + apply_mask(parser->buffer + payload_start, parser->header.payload_len, + parser->header.mask_key, 0); + WS_LOGI("WS: Mask applied to payload"); + } + + parser->state = WS_STATE_COMPLETE; + return 1; + } + } else { + parser->state = WS_STATE_ERROR; + WS_LOGE("WS: Buffer overflow in payload"); + return -1; + } + break; + } + + case WS_STATE_COMPLETE: + WS_LOGI("WS: Frame parsing complete, transitioning to COMPLETE state"); + return 1; + + case WS_STATE_ERROR: + WS_LOGE("WS: Parser is in error state"); + return -1; + + default: + WS_LOGE("WS: Unknown parser state: %d", parser->state); + parser->state = WS_STATE_ERROR; + return -1; + } + + return 0; // 继续解析 +} + +// 解析数据流 +int ws_parse_stream(ws_parser_t* parser, const uint8_t* data, size_t len) { + if (!parser || !data || len == 0) { + WS_LOGE("WS: Invalid parameters for ws_parse_stream"); + return -1; + } + + WS_LOGI("WS: Parsing stream data (%zu bytes), current state: %d, buffer_pos: %zu", + len, parser->state, parser->buffer_pos); + + // 如果解析器已经完成一个帧,重置状态 + if (parser->state == WS_STATE_COMPLETE) { + WS_LOGI("WS: Parser was in COMPLETE state, resetting for new frame"); + ws_parser_reset(parser); + } + + int total_processed = 0; + + for (size_t i = 0; i < len; i++) { + int result = ws_parse_byte(parser, data[i]); + + if (result == 1) { + // 帧解析完成 + WS_LOGI("WS: Complete frame parsed (%zu bytes total) opcode: %d, payload_len: %llu", + parser->buffer_pos, parser->header.opcode, (unsigned long long)parser->header.payload_len); + total_processed = i + 1; + break; + } else if (result == -1) { + // 解析错误 + WS_LOGE("WS: Parsing error at byte %zu", i); + ws_parser_reset(parser); + // return -1; + total_processed = i + 1; + } + // result == 0 继续解析 + } + + if (parser->state == WS_STATE_COMPLETE) { + WS_LOGI(" WS_STATE_COMPLETE at %d\n",total_processed); + } else if (parser->state == WS_STATE_ERROR) { + WS_LOGI(" WS_STATE_ERROR at %d\n",total_processed); + } else { + // 数据不完整,继续等待更多数据 + WS_LOGI("WS: Frame parsing incomplete, waiting for more data. State: %d, Buffer: %zu/%d, Payload remaining: %zu", + parser->state, parser->buffer_pos, WS_BUFFER_SIZE, parser->payload_remaining); + } + return total_processed; +} + +// 获取解析出的头部信息 +const ws_header_t* ws_get_header(ws_parser_t* parser) { + if (!parser || parser->state != WS_STATE_COMPLETE) { + return NULL; + } + return &parser->header; +} + +// 获取完整数据包(包含帧头) +const uint8_t* ws_get_packet(ws_parser_t* parser) { + if (!parser || parser->state != WS_STATE_COMPLETE) { + return NULL; + } + return parser->buffer; +} + +// 获取纯载荷数据 +const uint8_t* ws_get_payload(ws_parser_t* parser) { + if (!parser || parser->state != WS_STATE_COMPLETE) { + return NULL; + } + + // 计算载荷数据的起始位置 + // 帧头:2字节(基本头部) + size_t header_size = 2; + + // 扩展长度字段 + if (parser->header.payload_len == 126) { + header_size += 2; // 16位长度 + } else if (parser->header.payload_len == 127) { + header_size += 8; // 64位长度 + } + + // 掩码密钥 + if (parser->header.mask) { + header_size += 4; + } + + // 检查载荷数据是否在缓存范围内 + if (header_size + parser->header.payload_len > parser->buffer_pos) { + WS_LOGE("WS: Payload start position %zu exceeds buffer size %zu", header_size, parser->buffer_pos); + return NULL; + } + + return parser->buffer + header_size; +} + +// 获取载荷数据长度 +size_t ws_get_payload_length(ws_parser_t* parser) { + if (!parser || parser->state != WS_STATE_COMPLETE) { + return 0; + } + return parser->header.payload_len; +} + +// 检查解析器是否有错误 +int ws_parser_has_error(ws_parser_t* parser) { + return (parser && parser->state == WS_STATE_ERROR) ? 1 : 0; +} + +// 获取解析器当前状态 +ws_parse_state_t ws_parser_get_state(ws_parser_t* parser) { + return parser ? parser->state : WS_STATE_ERROR; +} + +// 销毁解析器 +void ws_parser_destroy(ws_parser_t* parser) { + if (parser) { + free(parser); + g_parser_count--; + + // 如果所有解析器都被销毁,释放全局缓存 + if (g_parser_count == 0 && g_ws_buffer) { + free(g_ws_buffer); + g_ws_buffer = NULL; + WS_LOGI("WS: Global buffer freed"); + } + + WS_LOGI("WS: Parser destroyed, remaining parsers: %d", g_parser_count); + } +} + +#ifdef __cplusplus +} +#endif +#if 1 +// 多包拆解测试函数 +void test_multiple_frames() { + printf("\n=== Multiple WebSocket Frames Test ===\n"); + + // 测试数据:包含多个WebSocket帧 + uint8_t test_data[] = { + // 第一个帧:5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第二个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 E6 A0 B7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF, + 0x99, 0xE6, 0xA0, 0xB7, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第三个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 74, 0x22, 0x3A, 0x22, 0xE7, 0x9A, + 0x84, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第四个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 95 B0 E5 AD 97 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x95, + 0xB0, 0xE5, 0xAD, 0x97, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第五个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 BB 84 E5 90 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE7, 0xBB, + 0x84, 0xE5, 0x90, 0x88, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第六个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 A2 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x91, + 0xA2, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第七个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E3 80 82 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE3, 0x80, + 0x82, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第八个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE4, 0xBD, + 0xA0, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第九个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 83 BD 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0x83, + 0xBD, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xAF, + 0xB4, 0xE8, 0xAF, 0xB4, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十一个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF, + 0x99, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十二个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 87 A0 E4 B8 AA 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x87, + 0xA0, 0xE4, 0xB8, 0xAA, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十三个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 95 B0 E5 AD 97 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x95, + 0xB0, 0xE5, 0xAD, 0x97, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十四个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 98 AF 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x98, + 0xAF, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D, + + // 第十五个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 9C A8 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + 0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x9C, + 0xA8, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, + 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D + }; + + size_t test_data_len = sizeof(test_data); + + printf("Test data length: %zu bytes\n", test_data_len); + printf("Test data (hex): "); + for (size_t i = 0; i < test_data_len; i++) { + printf("%02X ", test_data[i]); + if ((i + 1) % 16 == 0) printf("\n "); + } + printf("\n"); + + // 创建解析器 + ws_parser_t* parser = ws_parser_init(); + if (!parser) { + printf("Failed to create parser\n"); + return; + } + + // 多包拆解测试 + printf("\n=== Starting Multi-Frame Parsing ===\n"); + + size_t offset = 0; + int frame_count = 0; + + while (offset < test_data_len) { + printf("\n--- Frame %d ---\n", frame_count + 1); + printf("Remaining data: %zu bytes\n", test_data_len - offset); + + // 解析当前帧 + int result = ws_parse_stream(parser, test_data + offset, test_data_len - offset); + ws_parse_state_t ws_state = ws_parser_get_state(parser); + printf("ws_state: %d,result: %d\n", ws_state,result); + if (result > 0 && ws_state == WS_STATE_COMPLETE) { + frame_count++; + printf("Frame %d parsed successfully, consumed %d bytes\n", frame_count, result); + + const ws_header_t* header = ws_get_header(parser); + if (header) { + printf("Frame header:\n"); + printf(" FIN: %d\n", header->fin); + printf(" RSV: %d%d%d\n", header->rsv1, header->rsv2, header->rsv3); + printf(" Opcode: 0x%02X\n", header->opcode); + printf(" Mask: %d\n", header->mask); + printf(" Payload length: %llu\n", (unsigned long long)header->payload_len); + + if (header->mask) { + printf(" Mask key: 0x%02X%02X%02X%02X\n", + header->mask_key[0], header->mask_key[1], + header->mask_key[2], header->mask_key[3]); + } + } + + const uint8_t* payload = ws_get_payload(parser); + size_t payload_len = ws_get_payload_length(parser); + + if (payload && payload_len > 0) { + printf("Payload data:\n"); + printf(" Length: %zu bytes\n", payload_len); + printf(" Hex: "); + for (size_t i = 0; i < payload_len && i < 32; i++) { + printf("%02X ", payload[i]); + if ((i + 1) % 16 == 0) printf("\n "); + } + if (payload_len > 32) printf("..."); + printf("\n"); + + printf(" ASCII: "); + for (size_t i = 0; i < payload_len && i < 64; i++) { + if (payload[i] >= 32 && payload[i] <= 126) { + printf("%c", payload[i]); + } else { + printf("."); + } + } + if (payload_len > 64) printf("..."); + printf("\n"); + } + + + + // 重置解析器状态,准备解析下一个帧 + ws_parser_reset(parser); + + } else if (result > 0 && ws_state != WS_STATE_ERROR) { + printf("Parser state: %d reset \n", ws_parser_get_state(parser)); + // 重置解析器状态,准备解析下一个帧 + ws_parser_reset(parser); + } else { + printf("Incomplete frame, need more data\n"); + // printf("Parse error at offset %zu\n", offset); + // printf("Parser state: %d\n", ws_parser_get_state(parser)); + } + + // 移动到下一个帧 + offset += result; + // 添加安全检查 + if (offset >= test_data_len) { + printf("Reached end of data\n"); + break; + } + } + + printf("\n=== Multi-Frame Parsing Complete ===\n"); + printf("Total frames parsed: %d\n", frame_count); + printf("Total bytes processed: %zu\n", offset); + printf("Remaining bytes: %zu\n", test_data_len - offset); + + // 清理 + ws_parser_destroy(parser); +} + +// 单帧测试函数(保留原有功能) +void test_single_frame() { + printf("\n=== Single WebSocket Frame Test ===\n"); + + // 测试数据:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 E6 A0 B7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D + + // 测试数据:WebSocket帧 +uint8_t test_data[] = { + // WebSocket帧头: 81 7E (FIN=1, Opcode=1, Mask=0, PayloadLen=126) + 0x81, 0x7E, + + // 扩展长度: 00 BB (187字节) + 0x00, 0xBB, + + // 负载数据开始: 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 + 0x7B, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3A, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + + // 继续负载数据: 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 + 0x2C, 0x22, 0x6D, 0x73, 0x67, 0x22, 0x3A, 0x22, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, + + // 继续负载数据: 2C 22 74 61 73 6B 5F 69 64 22 3A 22 34 63 64 39 35 + 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x34, 0x63, 0x64, 0x39, 0x35, + + // 继续负载数据: 62 62 39 35 63 37 35 39 32 65 38 38 31 31 63 37 + 0x62, 0x62, 0x39, 0x35, 0x63, 0x37, 0x35, 0x39, 0x32, 0x65, 0x38, 0x38, 0x31, 0x31, 0x63, 0x37, + + // 继续负载数据: 65 37 65 36 64 33 36 65 39 32 35 22 2C 22 65 76 + 0x65, 0x37, 0x65, 0x36, 0x64, 0x33, 0x36, 0x65, 0x39, 0x32, 0x35, 0x22, 0x2C, 0x22, 0x65, 0x76, + + // 继续负载数据: 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 + 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x43, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x64, 0x22, 0x2C, 0x22, + + // 继续负载数据: 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 + 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x22, 0x3A, 0x7B, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, + + // 继续负载数据: 22 3A 22 E4 BD A0 EF BC 8C 22 2C 22 69 73 5F 65 + 0x22, 0x3A, 0x22, 0xE4, 0xBD, 0xA0, 0xEF, 0xBC, 0x8C, 0x22, 0x2C, 0x22, 0x69, 0x73, 0x5F, 0x65, + + // 继续负载数据: 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 + 0x6E, 0x64, 0x22, 0x3A, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x22, 0x2C, 0x22, 0x73, 0x65, 0x6E, 0x74, + + // 继续负载数据: 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 + 0x6E, 0x63, 0x65, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, 0x22, 0x73, 0x74, 0x61, 0x72, + + // 继续负载数据: 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74 + 0x74, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x22, 0x3A, 0x30, 0x22, 0x2C, 0x22, 0x65, 0x6E, 0x64, 0x5F, 0x74, + + // 继续负载数据: 69 6D 65 22 3A 30 7D 7D + 0x69, 0x6D, 0x65, 0x22, 0x3A, 0x30, 0x7D, 0x7D +}; + // uint8_t test_data[] = { + // 0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C, + // 0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF, + // 0x99, 0xE6, 0xA0, 0xB7, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, + // 0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, + // 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D + // }; + + size_t test_data_len = sizeof(test_data); + + printf("Test data length: %zu bytes\n", test_data_len); + printf("Test data (hex): "); + for (size_t i = 0; i < test_data_len; i++) { + printf("%02X ", test_data[i]); + if ((i + 1) % 16 == 0) printf("\n "); + } + printf("\n"); + + // 创建解析器 + ws_parser_t* parser = ws_parser_init(); + if (!parser) { + printf("Failed to create parser\n"); + return; + } + + // 解析数据 + int result = ws_parse_stream(parser, test_data, test_data_len); + + if (result > 0) { + printf("\n=== Parse Result ===\n"); + printf("Parsed bytes: %d\n", result); + + const ws_header_t* header = ws_get_header(parser); + if (header) { + printf("Frame header:\n"); + printf(" FIN: %d\n", header->fin); + printf(" RSV: %d%d%d\n", header->rsv1, header->rsv2, header->rsv3); + printf(" Opcode: 0x%02X\n", header->opcode); + printf(" Mask: %d\n", header->mask); + printf(" Payload length: %llu\n", (unsigned long long)header->payload_len); + + if (header->mask) { + printf(" Mask key: 0x%02X%02X%02X%02X\n", + header->mask_key[0], header->mask_key[1], + header->mask_key[2], header->mask_key[3]); + } + } + + const uint8_t* payload = ws_get_payload(parser); + size_t payload_len = ws_get_payload_length(parser); + + if (payload && payload_len > 0) { + printf("\nPayload data:\n"); + printf(" Length: %zu bytes\n", payload_len); + printf(" Hex: "); + for (size_t i = 0; i < payload_len && i < 64; i++) { + printf("%02X ", payload[i]); + if ((i + 1) % 16 == 0) printf("\n "); + } + if (payload_len > 64) printf("..."); + printf("\n"); + + printf(" ASCII: "); + for (size_t i = 0; i < payload_len && i < 64; i++) { + if (payload[i] >= 32 && payload[i] <= 126) { + printf("%c", payload[i]); + } else { + printf("."); + } + } + if (payload_len > 64) printf("..."); + printf("\n"); + } + + printf("\nParser state: %d\n", ws_parser_get_state(parser)); + + } else if (result == 0) { + printf("Incomplete frame, need more data\n"); + printf("Parser state: %d\n", ws_parser_get_state(parser)); + } else { + printf("Parse error\n"); + printf("Parser state: %d\n", ws_parser_get_state(parser)); + } + + // 清理 + ws_parser_destroy(parser); +} + +int main() { + printf("WebSocket Parser Standalone Test\n"); + printf("================================\n"); + + // 测试单帧解析 + test_single_frame(); + + // 测试多帧解析 + test_multiple_frames(); + + printf("\nAll tests completed.\n"); + return 0; +} + +#endif \ No newline at end of file diff --git a/test_ws_parser/websocket_simple_analysis.json b/test_ws_parser/websocket_simple_analysis.json new file mode 100644 index 000000000..daf483f88 --- /dev/null +++ b/test_ws_parser/websocket_simple_analysis.json @@ -0,0 +1,163 @@ +{ + "summary": { + "total_frames": 9, + "total_bytes": 503, + "valid_frames": 9, + "skipped_frames": 494 + }, + "frames": [ + { + "frame_index": 0, + "offset": 0, + "header": { + "fin": 1, + "rsv": 3, + "rsv_binary": "011", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 1, + "payload_length": 75 + }, + "frame_size": 81, + "payload_hex": "B2 CB 2C 65 94 15 47 92 C0 60 81 84 0E 08 10 50 C0 E5 96 4F FF F9 67 FF CB 2C A9 60 60 A0 81 CA 8F 21 91 91 97 FF FF FF C4 64 65 E4 65 FF E6 46 73 23 23 23 32 32 32 32 1F FF F3 23 76 76 76 76 79 38 D3 8B 28 B3 0F 2D A4 E2 CA", + "payload_utf8": ",e\u0015G`\u000e\b\u0010POg,``ʏ!deeFs###2222\u001f#vvvvy8Ӌ(\u000f-", + "payload_json": null + }, + { + "frame_index": 1, + "offset": 95, + "header": { + "fin": 0, + "rsv": 3, + "rsv_binary": "011", + "opcode": "0x08", + "opcode_name": "CLOSE", + "mask": 1, + "payload_length": 50 + }, + "frame_size": 56, + "payload_hex": "F3 48 C4 DF 18 BB F2 14 F4 28 45 5D 4E 34 E2 CA 3C C0 3A 4C 41 4D 45 33 2E 31 30 30 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA", + "payload_utf8": "H\u0018\u0014(E]N4<:LAME3.100", + "payload_json": null + }, + { + "frame_index": 2, + "offset": 151, + "header": { + "fin": 1, + "rsv": 2, + "rsv_binary": "010", + "opcode": "0x0A", + "opcode_name": "PONG", + "mask": 1, + "payload_length": 42 + }, + "frame_size": 48, + "payload_hex": "AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA", + "payload_utf8": "", + "payload_json": null + }, + { + "frame_index": 3, + "offset": 199, + "header": { + "fin": 1, + "rsv": 2, + "rsv_binary": "010", + "opcode": "0x0A", + "opcode_name": "PONG", + "mask": 1, + "payload_length": 42 + }, + "frame_size": 48, + "payload_hex": "AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA FF F3 48", + "payload_utf8": "H", + "payload_json": null + }, + { + "frame_index": 4, + "offset": 252, + "header": { + "fin": 1, + "rsv": 7, + "rsv_binary": "111", + "opcode": "0x08", + "opcode_name": "CLOSE", + "mask": 0, + "payload_length": 52 + }, + "frame_size": 54, + "payload_hex": "18 4D CC AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA", + "payload_utf8": "\u0018M̪", + "payload_json": null + }, + { + "frame_index": 5, + "offset": 306, + "header": { + "fin": 1, + "rsv": 2, + "rsv_binary": "010", + "opcode": "0x0A", + "opcode_name": "PONG", + "mask": 1, + "payload_length": 42 + }, + "frame_size": 48, + "payload_hex": "AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA", + "payload_utf8": "", + "payload_json": null + }, + { + "frame_index": 6, + "offset": 354, + "header": { + "fin": 1, + "rsv": 2, + "rsv_binary": "010", + "opcode": "0x0A", + "opcode_name": "PONG", + "mask": 1, + "payload_length": 42 + }, + "frame_size": 48, + "payload_hex": "AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 81 72 7B 22 68 65 61 64 65 72 22 3A 7B 22", + "payload_utf8": "r{\"header\":{\"", + "payload_json": null + }, + { + "frame_index": 7, + "offset": 407, + "header": { + "fin": 0, + "rsv": 2, + "rsv_binary": "010", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 58 + }, + "frame_size": 60, + "payload_hex": "22 45 6E 64 53 79 6E 74 68 65 73 69 73 22 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 74 61 73 6B 5F 69 64 22", + "payload_utf8": "\"EndSynthesis\",\"msg\":\"success\",\"status\":20000000,\"task_id\"", + "payload_json": null + }, + { + "frame_index": 8, + "offset": 467, + "header": { + "fin": 0, + "rsv": 3, + "rsv_binary": "011", + "opcode": "0x0A", + "opcode_name": "PONG", + "mask": 0, + "payload_length": 34 + }, + "frame_size": 36, + "payload_hex": "37 63 30 31 36 37 61 63 63 30 61 37 32 31 38 37 65 33 64 61 31 31 39 61 36 61 35 61 62 62 33 30 22 7D", + "payload_utf8": "7c0167acc0a72187e3da119a6a5abb30\"}", + "payload_json": null + } + ] +} \ No newline at end of file diff --git a/test_ws_parser/websocket_simple_analysis.py b/test_ws_parser/websocket_simple_analysis.py new file mode 100644 index 000000000..f84377408 --- /dev/null +++ b/test_ws_parser/websocket_simple_analysis.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +简化版WebSocket数据解析工具 - 增强版,确保RSV位验证 +""" + +import json +import re + +def hex_to_bytes(hex_string): + """将十六进制字符串转换为字节""" + hex_string = re.sub(r'\s+', '', hex_string) + return bytes.fromhex(hex_string) + +def get_opcode_name(opcode): + """获取操作码名称""" + opcode_names = { + 0x0: "CONTINUATION", + 0x1: "TEXT", + 0x2: "BINARY", + 0x8: "CLOSE", + 0x9: "PING", + 0xA: "PONG" + } + return opcode_names.get(opcode, f"UNKNOWN(0x{opcode:02X})") + +def analyze_websocket_frames(hex_data): + """分析WebSocket帧,确保只有RSV位为0的帧才有效""" + data = hex_data + frames = [] + offset = 0 + skipped_count = 0 + + print(f"开始分析WebSocket数据,总长度: {len(data)} 字节") + + while offset < len(data): + if offset + 2 > len(data): + break + + # 解析帧头 + first_byte = data[offset] + second_byte = data[offset + 1] + + fin = (first_byte >> 7) & 0x1 + rsv = (first_byte >> 4) & 0x7 + opcode = first_byte & 0x0F + mask = (second_byte >> 7) & 0x1 + payload_len = second_byte & 0x7F + + # 验证RSV位 - 只有RSV为0的帧才有效 + # if rsv != 0: + # print(f"跳过无效帧: 偏移={offset}, RSV={rsv:03b} (非0), 第一个字节=0x{first_byte:02X}") + # offset += 1 # 跳过1字节,继续搜索 + # skipped_count += 1 + # continue + + # 验证操作码是否有效 + valid_opcodes = [0x0, 0x1, 0x2, 0x8, 0x9, 0xA] # CONTINUATION, TEXT, BINARY, CLOSE, PING, PONG + if opcode not in valid_opcodes: + print(f"跳过无效帧: 偏移={offset}, 操作码=0x{opcode:02X} (无效), 第一个字节=0x{first_byte:02X}") + offset += 1 # 跳过1字节,继续搜索 + skipped_count += 1 + continue + + # 计算帧头大小 + header_size = 2 + if payload_len == 126: + if offset + 4 <= len(data): + extended_len = int.from_bytes(data[offset+2:offset+4], 'big') + header_size += 2 + else: + extended_len = 0 + elif payload_len == 127: + if offset + 10 <= len(data): + extended_len = int.from_bytes(data[offset+2:offset+10], 'big') + header_size += 8 + else: + extended_len = 0 + else: + extended_len = payload_len + + if mask: + header_size += 4 + + total_frame_size = header_size + extended_len + + if offset + total_frame_size > len(data): + break + + # 提取负载 + payload_start = offset + header_size + payload_data = data[payload_start:payload_start + extended_len] + + # 尝试解析JSON + json_content = None + try: + if payload_data: + json_content = json.loads(payload_data.decode('utf-8')) + except: + pass + + # 构建帧信息 + frame_info = { + "frame_index": len(frames), + "offset": offset, + "header": { + "fin": fin, + "rsv": rsv, + "rsv_binary": f"{rsv:03b}", # 添加二进制表示 + "opcode": f"0x{opcode:02X}", + "opcode_name": get_opcode_name(opcode), # 添加操作码名称 + "mask": mask, + "payload_length": extended_len + }, + "frame_size": total_frame_size, + "payload_hex": payload_data.hex(' ').upper() if payload_data else "", + "payload_utf8": payload_data.decode('utf-8', errors='ignore') if payload_data else "", + "payload_json": json_content + } + + frames.append(frame_info) + print(f"发现有效帧: 偏移={offset}, 操作码={get_opcode_name(opcode)}, 大小={total_frame_size}字节, RSV={rsv:03b}") + offset += total_frame_size + + print(f"分析完成: 有效帧={len(frames)}, 跳过帧={skipped_count}") + return frames + +def main(): + # 原始十六进制数据 + hex_data = """B2 CB 25 96 59 64 B2 CB 2C 65 94 15 47 92 C0 60 + 81 84 0E 08 10 50 C0 E5 96 4F FF F9 67 FF CB 2C + A9 60 60 A0 81 CA 8F 21 91 91 97 FF FF FF C4 64 + 65 E4 65 FF E6 46 73 23 23 23 32 32 32 32 1F FF + F3 23 76 76 76 76 79 38 D3 8B 28 B3 0F 2D A4 E2 + CA 2C C3 DD A6 9D 9C C3 DD 9D 9D 9D 9C D3 8D 38 + B2 8B 28 B3 FF F3 48 C4 DF 18 BB F2 14 F4 28 45 + 5D 4E 34 E2 CA 3C C0 3A 4C 41 4D 45 33 2E 31 30 + 30 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA FF F3 48 C4 EF 1C A4 14 F8 34 18 4D + CC AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA + AA AA AA AA 81 72 7B 22 68 65 61 64 65 72 22 3A + 7B 22 65 76 65 6E 74 22 3A 22 45 6E 64 53 79 6E + 74 68 65 73 69 73 22 2C 22 6D 73 67 22 3A 22 73 + 75 63 63 65 73 73 22 2C 22 73 74 61 74 75 73 22 + 3A 32 30 30 30 30 30 30 30 2C 22 74 61 73 6B 5F + 69 64 22 3A 22 37 63 30 31 36 37 61 63 63 30 61 + 37 32 31 38 37 65 33 64 61 31 31 39 61 36 61 35 + 61 62 62 33 30 22 7D""" + + # 转换为字节 + data = hex_to_bytes(hex_data) + + # 分析帧 + frames = analyze_websocket_frames(data) + + # 生成输出 + output = { + "summary": { + "total_frames": len(frames), + "total_bytes": len(data), + "valid_frames": len(frames), + "skipped_frames": len(data) - len(frames) # 估算跳过的帧数 + }, + "frames": frames + } + + # 保存到文件 + with open("websocket_simple_analysis.json", "w", encoding="utf-8") as f: + json.dump(output, f, ensure_ascii=False, indent=2) + + print(f"分析完成,共发现 {len(frames)} 个有效WebSocket帧") + print("结果已保存到 websocket_simple_analysis.json") + + # 打印前几个帧的摘要 + for i, frame in enumerate(frames[:5]): + print(f"\n帧 {i+1}:") + print(f" 偏移: {frame['offset']}") + print(f" 大小: {frame['frame_size']} 字节") + print(f" FIN: {frame['header']['fin']}") + print(f" RSV: {frame['header']['rsv_binary']} ({frame['header']['rsv']})") + print(f" 操作码: {frame['header']['opcode']} ({frame['header']['opcode_name']})") + print(f" 负载长度: {frame['header']['payload_length']}") + if frame['payload_json']: + print(f" JSON内容: {frame['payload_json']}") + +if __name__ == "__main__": + main() \ No newline at end of file -- 2.17.1