From ce6d2dfa35890184f253ec2e682528b9f37fdb89 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=AD=99=E6=98=A5=E9=98=B3?= Date: Fri, 15 Aug 2025 10:43:39 +0800 Subject: [PATCH] =?utf8?q?=E4=BC=98=E5=8C=96websocket=E5=8D=8F=E8=AE=AE?= =?utf8?q?=E8=A7=A3=E6=9E=90=E4=BB=A3=E7=A0=81=20=E8=A7=A3=E5=86=B3?= =?utf8?q?=E5=B7=B2=E7=BB=8F=E6=97=A0=E6=95=B0=E6=8D=AE=E4=BD=86=E6=98=AF?= =?utf8?q?=E8=BF=98=E6=98=AF=E5=AE=8C=E6=88=90=E8=A7=A3=E5=8C=85=E7=9A=84b?= =?utf8?q?ug?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../slip/cat1Service/websocket_parser.cpp | 343 +------------- test_ws_parser/Makefile | 2 +- test_ws_parser/data1.hex | 62 +++ test_ws_parser/data2.hex | 64 +++ .../websocket_parser_standalone.cpp | 396 +--------------- test_ws_parser/websocket_parser_test.cpp | 166 +++++++ test_ws_parser/websocket_simple_analysis.json | 440 ++++++++++++++---- test_ws_parser/websocket_simple_analysis.py | 153 ++++-- test_ws_parser/websocket_test | Bin 0 -> 26480 bytes 9 files changed, 770 insertions(+), 856 deletions(-) create mode 100644 test_ws_parser/data1.hex create mode 100644 test_ws_parser/data2.hex create mode 100644 test_ws_parser/websocket_parser_test.cpp create mode 100644 test_ws_parser/websocket_test diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/websocket_parser.cpp b/code/sdk/drivers/peripheral/slip/cat1Service/websocket_parser.cpp index aa259147a..889c0f197 100644 --- a/code/sdk/drivers/peripheral/slip/cat1Service/websocket_parser.cpp +++ b/code/sdk/drivers/peripheral/slip/cat1Service/websocket_parser.cpp @@ -198,7 +198,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { } // 检查RSV位是否都为0(根据RFC6455规范) - if (!(parser->header.fin == 1 && parser->header.rsv1 == 0 && parser->header.rsv2 == 0 && parser->header.rsv3 == 0)) + if (!(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); @@ -312,11 +312,8 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { if (parser->payload_remaining == 0) { // 计算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; + 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[1], len_bytes[0]); @@ -403,7 +400,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { if (parser->header.mask) { WS_LOGI("WS: Moving to READ_MASK state"); parser->state = WS_STATE_READ_MASK; - return 1; + return 0; } else { if (parser->payload_remaining == 0) { WS_LOGI("WS: Zero payload, moving to COMPLETE state"); @@ -514,19 +511,18 @@ int ws_parse_stream(ws_parser_t* parser, const uint8_t* data, size_t len) { for (size_t i = 0; i < len; i++) { int result = ws_parse_byte(parser, data[i]); + total_processed = i + 1; // 始终统计已消费字节数 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; + break; // 让上层根据 total_processed 前进 } // result == 0 继续解析 } @@ -628,330 +624,3 @@ void ws_parser_destroy(ws_parser_t* parser) { #ifdef __cplusplus } #endif -#if 0 -// 多包拆解测试函数 -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 - 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/Makefile b/test_ws_parser/Makefile index 99a8e6d62..89d1c98c6 100644 --- a/test_ws_parser/Makefile +++ b/test_ws_parser/Makefile @@ -1,7 +1,7 @@ CC = gcc CFLAGS = -Wall -Wextra -std=c99 -O2 TARGET = websocket_test -SOURCE = websocket_parser_standalone.cpp +SOURCE = websocket_parser_test.cpp # 默认目标 all: $(TARGET) diff --git a/test_ws_parser/data1.hex b/test_ws_parser/data1.hex new file mode 100644 index 000000000..2e432525f --- /dev/null +++ b/test_ws_parser/data1.hex @@ -0,0 +1,62 @@ +65 1C CA 5A A5 1E C3 CA BA E2 2D 0A 3A FF 41 22 +2A 59 46 AF 61 2A 48 AA 02 D2 51 24 64 29 81 A7 +21 B6 64 FD 88 4B 8D 77 70 F9 11 CC A4 19 12 43 +01 A8 9F 56 C0 2C 0C 64 0B A1 0D CA F6 1E EA 25 +D9 4B 8A 04 DE F2 B5 90 78 32 CE 7E E3 45 97 EE +02 BE 56 D8 29 BF BF FF D5 36 7F AD A7 45 2F 1F +3D DE A4 5B 57 A3 77 4A 09 8A EA CF A0 79 D6 BD +DF 6E FE A9 B8 D6 AD BF FE 47 FF A3 EF 5D 28 CE +68 A9 C9 C0 B9 A5 17 53 08 3A F0 44 FF F3 48 C4 +74 19 42 42 54 14 DA 4A C8 21 E7 33 52 38 7A 7C +A6 30 45 79 8F 24 04 1D 06 8C DE 22 5D 65 6B A8 +F6 31 AB 75 84 E9 F6 35 83 61 98 E7 A4 D3 0F 3F +51 E9 89 67 91 59 98 6A B7 11 80 85 56 55 61 42 +82 E1 AD 38 BB 29 57 5B E9 F3 B7 A3 5A 75 7F 59 +7A 00 8B 23 20 E9 50 03 00 63 95 BC 73 95 BA AD +46 1C 10 A8 C7 36 FD 8E B1 64 54 A9 46 54 CA 4E +46 6A BA DA 45 99 2F A7 A5 29 9F 74 06 A3 25 E5 +A3 D5 88 CF 2E 7D 4B AF F3 18 C5 52 FF F3 48 C4 +92 15 A0 56 44 0C 7E 18 24 95 AF 9B 44 77 47 5B +2D 55 6E 6B A5 F5 2A D5 5B CD 65 23 5F 6A 7B 2A +2E E5 4B 65 5D 27 AD 48 A5 38 40 E2 9E 76 59 D8 +AE 7F CF BE 61 13 30 4C 17 55 4C 41 4D 45 55 55 +00 6A 96 BE AE EA 82 65 89 30 C1 B8 2B 24 1D 9D +1A 58 F5 68 73 4B 56 71 C4 45 A7 98 54 6E 22 5A +14 05 66 A7 4C 3D 86 96 02 F4 B6 E6 87 14 05 88 +B7 2A 45 A4 85 69 DF AD D6 50 7A C5 0E 41 5A 9B +D7 B2 A6 38 59 02 CD 40 A9 9B 99 17 FF F3 48 C4 +BE 1A DB 6E 24 4A 60 C4 7D 3A A0 AC 19 40 B0 E5 +4C 41 4D 45 33 2E 31 30 30 55 55 55 55 55 55 55 +55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 +55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 +55 55 55 55 55 55 55 55 55 55 55 55 82 7E 01 60 +55 55 04 A7 36 8D C9 65 92 BC 48 8A EE 0E 89 4B +59 88 95 3A C5 15 53 CE D2 8A 9E 74 F1 54 73 C5 +91 FA B2 28 2A 59 77 E5 8A AD C7 90 CF F6 11 45 +F1 29 61 E7 49 16 5B 8E FA 9F 4D 87 4B 79 55 B9 +FF F3 48 C4 CF 14 A0 12 31 94 18 44 00 FF FF E4 +A5 76 1D 4A 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 C1 11 28 06 22 5E 00 46 00 AA AA AA +AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA +AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA +AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA +AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA +AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA +AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA +AA AA AA AA AA AA AA AA 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 63 66 38 62 32 65 63 39 61 33 34 39 65 35 30 +31 61 36 33 61 36 33 30 32 38 62 61 38 36 38 31 +34 22 7D 7D \ No newline at end of file diff --git a/test_ws_parser/data2.hex b/test_ws_parser/data2.hex new file mode 100644 index 000000000..f4ba1ec46 --- /dev/null +++ b/test_ws_parser/data2.hex @@ -0,0 +1,64 @@ +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 AC 91 E7 9D 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 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 9B 9E E5 A4 8D 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 47 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 EF BC +9A 5C 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 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 A5 BD 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 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 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 A6 88 E5 A6 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 4B 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 5C 22 5C 6E 5C 6E 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 +88 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 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 94 BE E4 B8 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 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 89 8B E6 9C BA 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 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 E9 97 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 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 E9 93 83 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 +93 8D E4 BA 86 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 \ No newline at end of file diff --git a/test_ws_parser/websocket_parser_standalone.cpp b/test_ws_parser/websocket_parser_standalone.cpp index c02304b2f..0cc9f8ccc 100644 --- a/test_ws_parser/websocket_parser_standalone.cpp +++ b/test_ws_parser/websocket_parser_standalone.cpp @@ -198,7 +198,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { } // 检查RSV位是否都为0(根据RFC6455规范) - if (!(parser->header.fin == 1 && parser->header.rsv1 == 0 && parser->header.rsv2 == 0 && parser->header.rsv3 == 0)) + if (!(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); @@ -399,7 +399,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) { if (parser->header.mask) { WS_LOGI("WS: Moving to READ_MASK state"); parser->state = WS_STATE_READ_MASK; - return 1; + return 0; } else { if (parser->payload_remaining == 0) { WS_LOGI("WS: Zero payload, moving to COMPLETE state"); @@ -418,7 +418,16 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t 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; + WS_LOGI("WS: Buffer overflow in mask"); + return -1; + } + + // 掩码密钥共4字节 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], @@ -501,21 +510,20 @@ int ws_parse_stream(ws_parser_t* parser, const uint8_t* data, size_t len) { for (size_t i = 0; i < len; i++) { int result = ws_parse_byte(parser, data[i]); + total_processed = i + 1; // 始终统计已消费字节数 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; + break; // 让上层根据 total_processed 前进 } - // result == 0 继续解析 + // result == 0 继续解析直到数据用尽 } if (parser->state == WS_STATE_COMPLETE) { @@ -553,7 +561,7 @@ const uint8_t* ws_get_payload(ws_parser_t* parser) { } // 计算载荷数据的起始位置 - // 帧头:2字节(基本头部) + // 注意:当前实现仅将基本2字节头和负载写入缓冲,未写入扩展长度与掩码字节 size_t header_size = 2; // 扩展长度字段 @@ -615,375 +623,3 @@ void ws_parser_destroy(ws_parser_t* parser) { #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_parser_test.cpp b/test_ws_parser/websocket_parser_test.cpp new file mode 100644 index 000000000..f1f9160f9 --- /dev/null +++ b/test_ws_parser/websocket_parser_test.cpp @@ -0,0 +1,166 @@ +#include "websocket_parser_standalone.cpp" +#include +#include + +// 多包拆解测试函数 + +void decode_data(ws_parser_t* parser,uint8_t* data, size_t len) { + + + printf("Test data length: %zu bytes\n", len); + printf("Test data (hex): "); + for (size_t i = 0; i < len; i++) { + printf("%02X ", data[i]); + if ((i + 1) % 16 == 0) printf("\n "); + } + printf("\n"); + + size_t offset = 0; + int frame_count = 0; + + while (offset < len) { + printf("\n--- Frame %d ---\n", frame_count + 1); + printf("Remaining data: %zu bytes\n", len - offset); + + // 解析当前帧 + int result = ws_parse_stream(parser, data + offset, 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++) { + // 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++) { + for (size_t i = 0; i < payload_len ; 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) { + printf("Parse error, resetting parser\n"); + ws_parser_reset(parser); + } else { + printf("Incomplete frame, need more data\n"); + } + + // 移动到下一个帧 + offset += result; + // 添加安全检查 + if (offset >= 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", len - offset); + +} + +void test_multiple_frames() { + printf("\n=== Multiple WebSocket Frames Test ===\n"); + + // #include "data1.c" + // #include "data2.c" + #define data1_filename "/home/snicker/fd230_650/test_ws_parser/data1.bin" + #define data2_filename "/home/snicker/fd230_650/test_ws_parser/data2.bin" + printf("Opening files...\n"); + printf("data1 path: %s\n", data1_filename); + printf("data2 path: %s\n", data2_filename); + FILE *file1 = fopen(data1_filename, "rb"); + FILE *file2 = fopen(data2_filename, "rb"); + printf("file1=%p file2=%p\n", (void*)file1, (void*)file2); + if (!file1) { printf("fopen data1 failed: %s\n", strerror(errno)); } + if (!file2) { printf("fopen data2 failed: %s\n", strerror(errno)); } + if (!file1 || !file2) { printf("Failed to open files\n"); return; } + fseek(file1, 0, SEEK_END); + size_t data1_size = ftell(file1); + fseek(file2, 0, SEEK_END); + size_t data2_size = ftell(file2); + fseek(file1, 0, SEEK_SET); + fseek(file2, 0, SEEK_SET); + printf("sizes: data1=%zu data2=%zu\n", data1_size, data2_size); + uint8_t *data1 = (uint8_t *)malloc(data1_size); + uint8_t *data2 = (uint8_t *)malloc(data2_size); + printf("malloc: data1=%p data2=%p\n", (void*)data1, (void*)data2); + size_t r1 = fread(data1, 1, data1_size, file1); + size_t r2 = fread(data2, 1, data2_size, file2); + printf("fread: r1=%zu r2=%zu\n", r1, r2); + fclose(file1); + fclose(file2); + + // 创建解析器 + printf("Creating parser...\n"); + ws_parser_t* parser = ws_parser_init(); + printf("parser=%p\n", (void*)parser); + if (!parser) { + printf("Failed to create parser\n"); + return; + } + + // 多包拆解测试 + printf("\n=== Starting Multi-Frame Parsing ===\n"); + decode_data(parser,data1,data1_size); + // decode_data(parser,data2,data2_size); + // 清理 + ws_parser_destroy(parser); +} + +int main() { + printf("WebSocket Parser Standalone Test\n"); + printf("================================\n"); + + // 测试多帧解析 + test_multiple_frames(); + + printf("\nAll tests completed.\n"); + return 0; +} \ No newline at end of file diff --git a/test_ws_parser/websocket_simple_analysis.json b/test_ws_parser/websocket_simple_analysis.json index daf483f88..64c080b61 100644 --- a/test_ws_parser/websocket_simple_analysis.json +++ b/test_ws_parser/websocket_simple_analysis.json @@ -1,163 +1,415 @@ { "summary": { - "total_frames": 9, - "total_bytes": 503, - "valid_frames": 9, - "skipped_frames": 494 + "total_frames": 20, + "total_bytes": 977, + "valid_frames": 20, + "skipped_frames": 957 }, "frames": [ { "frame_index": 0, - "offset": 0, + "offset": 11, "header": { - "fin": 1, - "rsv": 3, - "rsv_binary": "011", - "opcode": "0x02", - "opcode_name": "BINARY", - "mask": 1, - "payload_length": 75 + "fin": 0, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x0A", + "opcode_name": "PONG", + "mask": 0, + "payload_length": 58 }, - "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-", + "frame_size": 60, + "payload_hex": "FF 41 22 2A 59 46 AF 61 2A 48 AA 02 D2 51 24 64 29 81 A7 21 B6 64 FD 88 4B 8D 77 70 F9 11 CC A4 19 12 43 01 A8 9F 56 C0 2C 0C 64 0B A1 0D CA F6 1E EA 25 D9 4B 8A 04 DE F2 B5", + "payload_utf8": "A\"*YFa*H\u0002Q$d)!dKwp\u0011̤\u0019\u0012C\u0001V,\fd\u000b\r\u001e%K\u0004", "payload_json": null }, { "frame_index": 1, - "offset": 95, + "offset": 80, "header": { "fin": 0, - "rsv": 3, - "rsv_binary": "011", - "opcode": "0x08", - "opcode_name": "CLOSE", + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", "mask": 1, - "payload_length": 50 + "payload_length": 62 }, - "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", + "frame_size": 68, + "payload_hex": "BF FF D5 36 7F AD A7 45 2F 1F 3D DE A4 5B 57 A3 77 4A 09 8A EA CF A0 79 D6 BD DF 6E FE A9 B8 D6 AD BF FE 47 FF A3 EF 5D 28 CE 68 A9 C9 C0 B9 A5 17 53 08 3A F0 44 FF F3 48 C4 74 19 42 42", + "payload_utf8": "6E/\u001f=ޤ[WwJ\tϠyֽn֭G](h\u0017S\b:DHt\u0019BB", "payload_json": null }, { "frame_index": 2, - "offset": 151, + "offset": 194, "header": { "fin": 1, - "rsv": 2, - "rsv_binary": "010", - "opcode": "0x0A", - "opcode_name": "PONG", - "mask": 1, - "payload_length": 42 + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x09", + "opcode_name": "PING", + "mask": 0, + "payload_length": 103 }, - "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": "", + "frame_size": 105, + "payload_hex": "91 59 98 6A B7 11 80 85 56 55 61 42 82 E1 AD 38 BB 29 57 5B E9 F3 B7 A3 5A 75 7F 59 7A 00 8B 23 20 E9 50 03 00 63 95 BC 73 95 BA AD 46 1C 10 A8 C7 36 FD 8E B1 64 54 A9 46 54 CA 4E 46 6A BA DA 45 99 2F A7 A5 29 9F 74 06 A3 25 E5 A3 D5 88 CF 2E 7D 4B AF F3 18 C5 52 FF F3 48 C4 92 15 A0 56 44 0C 7E 18 24 95 AF", + "payload_utf8": "Yj\u0011VUaB8)W[ZuYz\u0000# P\u0003\u0000csF\u001c\u00106dTFTNFjE/)t\u0006%Ո.}K\u0018RHĒ\u0015VD\f~\u0018$", "payload_json": null }, { "frame_index": 3, - "offset": 199, + "offset": 352, "header": { - "fin": 1, - "rsv": 2, - "rsv_binary": "010", - "opcode": "0x0A", - "opcode_name": "PONG", - "mask": 1, - "payload_length": 42 + "fin": 0, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x00", + "opcode_name": "CONTINUATION", + "mask": 0, + "payload_length": 106 }, - "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", + "frame_size": 108, + "payload_hex": "96 BE AE EA 82 65 89 30 C1 B8 2B 24 1D 9D 1A 58 F5 68 73 4B 56 71 C4 45 A7 98 54 6E 22 5A 14 05 66 A7 4C 3D 86 96 02 F4 B6 E6 87 14 05 88 B7 2A 45 A4 85 69 DF AD D6 50 7A C5 0E 41 5A 9B D7 B2 A6 38 59 02 CD 40 A9 9B 99 17 FF F3 48 C4 BE 1A DB 6E 24 4A 60 C4 7D 3A A0 AC 19 40 B0 E5 4C 41 4D 45 33 2E 31 30 30 55 55 55", + "payload_utf8": "e0+$\u001d\u001aXhsKVqETn\"Z\u0014\u0005fL=\u0002\u0014\u0005*Ei߭Pz\u000eAZײ8Y\u0002@\u0017Hľ\u001an$J`}:\u0019@LAME3.100UUU", "payload_json": null }, { "frame_index": 4, - "offset": 252, + "offset": 508, "header": { "fin": 1, - "rsv": 7, - "rsv_binary": "111", - "opcode": "0x08", - "opcode_name": "CLOSE", + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", "mask": 0, - "payload_length": 52 + "payload_length": 352 }, - "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̪", + "frame_size": 356, + "payload_hex": "55 55 04 A7 36 8D C9 65 92 BC 48 8A EE 0E 89 4B 59 88 95 3A C5 15 53 CE D2 8A 9E 74 F1 54 73 C5 91 FA B2 28 2A 59 77 E5 8A AD C7 90 CF F6 11 45 F1 29 61 E7 49 16 5B 8E FA 9F 4D 87 4B 79 55 B9 FF F3 48 C4 CF 14 A0 12 31 94 18 44 00 FF FF E4 A5 76 1D 4A 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 C1 11 28 06 22 5E 00 46 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 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": "UU\u00046eH\u000eKY:\u0015SҊtTső(*Yw劭ǐ\u0011E)aI\u0016[MKyUH\u0014\u00121\u0018D\u0000v\u001dJLAME3.100H\u0011(\u0006\"^\u0000F\u0000", "payload_json": null }, { "frame_index": 5, - "offset": 306, + "offset": 864, "header": { "fin": 1, - "rsv": 2, - "rsv_binary": "010", - "opcode": "0x0A", - "opcode_name": "PONG", - "mask": 1, - "payload_length": 42 + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x01", + "opcode_name": "TEXT", + "mask": 0, + "payload_length": 114 }, - "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": "", + "frame_size": 116, + "payload_hex": "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 63 66 38 62 32 65 63 39 61 33 34 39 65 35 30 31 61 36 33 61 36 33 30 32 38 62 61 38 36 38 31 34 74 79 70", + "payload_utf8": "{\"header\":{\"event\":\"EndSynthesis\",\"msg\":\"success\",\"status\":20000000,\"task_id\":\"cf8b2ec9a349e501a63a63028ba86814typ", "payload_json": null }, { "frame_index": 6, - "offset": 354, + "offset": 1008, "header": { "fin": 1, - "rsv": 2, - "rsv_binary": "010", - "opcode": "0x0A", - "opcode_name": "PONG", - "mask": 1, - "payload_length": 42 + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x00", + "opcode_name": "CONTINUATION", + "mask": 0, + "payload_length": 34 }, - "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\":{\"", + "frame_size": 36, + "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", + "payload_utf8": ",\"task_id\":\"\",\"reasoning_content\":", "payload_json": null }, { "frame_index": 7, - "offset": 407, + "offset": 1047, "header": { - "fin": 0, - "rsv": 2, - "rsv_binary": "010", + "fin": 1, + "rsv": 0, + "rsv_binary": "000", "opcode": "0x02", "opcode_name": "BINARY", "mask": 0, - "payload_length": 58 + "payload_length": 72 }, - "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_size": 74, + "payload_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 9B 9E E5 A4 8D 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"回复\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "回复", + "task_id": "", + "reasoning_content": "" + } }, { "frame_index": 8, - "offset": 467, + "offset": 1121, "header": { - "fin": 0, - "rsv": 3, - "rsv_binary": "011", - "opcode": "0x0A", - "opcode_name": "PONG", + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", "mask": 0, - "payload_length": 34 + "payload_length": 71 }, - "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 + "frame_size": 73, + "payload_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 EF BC 9A 5C 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\":\\\"\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": ":\"", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 9, + "offset": 1194, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 72 + }, + "frame_size": 74, + "payload_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 A5 BD 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"好的\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "好的", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 10, + "offset": 1268, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 69 + }, + "frame_size": 71, + "payload_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 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\",\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": ",", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 11, + "offset": 1339, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 72 + }, + "frame_size": 74, + "payload_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 A6 88 E5 A6 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"妈妈\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "妈妈", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 12, + "offset": 1413, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 75 + }, + "frame_size": 77, + "payload_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 E3 80 82 5C 22 5C 6E 5C 6E 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"。\\\"\\n\\n\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "。\"\n\n", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 13, + "offset": 1490, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 69 + }, + "frame_size": 71, + "payload_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 88 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"刚\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "刚", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 14, + "offset": 1561, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 72 + }, + "frame_size": 74, + "payload_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 E6 94 BE E4 B8 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"放下\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "放下", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 15, + "offset": 1635, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 72 + }, + "frame_size": 74, + "payload_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 E6 89 8B E6 9C BA 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"手机\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "手机", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 16, + "offset": 1709, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 69 + }, + "frame_size": 71, + "payload_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 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\",\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": ",", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 17, + "offset": 1780, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 69 + }, + "frame_size": 71, + "payload_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 E9 97 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"门\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "门", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 18, + "offset": 1851, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 69 + }, + "frame_size": 71, + "payload_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 E9 93 83 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"铃\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "铃", + "task_id": "", + "reasoning_content": "" + } + }, + { + "frame_index": 19, + "offset": 1922, + "header": { + "fin": 1, + "rsv": 0, + "rsv_binary": "000", + "opcode": "0x02", + "opcode_name": "BINARY", + "mask": 0, + "payload_length": 72 + }, + "frame_size": 74, + "payload_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 93 8D E4 BA 86 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", + "payload_utf8": "{\"type\":\"middle\",\"content\":\"响了\",\"task_id\":\"\",\"reasoning_content\":\"\"}", + "payload_json": { + "type": "middle", + "content": "响了", + "task_id": "", + "reasoning_content": "" + } } ] } \ No newline at end of file diff --git a/test_ws_parser/websocket_simple_analysis.py b/test_ws_parser/websocket_simple_analysis.py index f84377408..90f528026 100644 --- a/test_ws_parser/websocket_simple_analysis.py +++ b/test_ws_parser/websocket_simple_analysis.py @@ -48,11 +48,11 @@ def analyze_websocket_frames(hex_data): 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 + 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 @@ -124,48 +124,111 @@ def analyze_websocket_frames(hex_data): print(f"分析完成: 有效帧={len(frames)}, 跳过帧={skipped_count}") return frames +def hex_to_c_array(hex_string, array_name="data", output_file="output.c"): + """ + 将十六进制字符串转换为C语言数组并写入文件 + + Args: + hex_string (str): 十六进制字符串,可以包含空格或0x前缀 + array_name (str): C数组的名称 + output_file (str): 输出文件名 + """ + # 清理十六进制字符串,移除空格和0x前缀 + hex_clean = hex_string.replace(" ", "").replace("0x", "").replace("0X", "") + + # 验证十六进制字符串 + try: + # 转换为字节数组 + bytes_data = bytes.fromhex(hex_clean) + except ValueError as e: + print(f"错误:无效的十六进制字符串 - {e}") + return False + + # 生成C数组内容 + c_array = f"// 自动生成的C数组\n" + c_array += f"// 数组大小: {len(bytes_data)} 字节\n\n" + c_array += f"unsigned char {array_name}[] = {{\n" + + # 每行16个字节,格式化输出 + for i in range(0, len(bytes_data), 16): + line_bytes = bytes_data[i:i+16] + hex_values = [f"0x{b:02X}" for b in line_bytes] + c_array += f" {', '.join(hex_values)}" + + # 如果不是最后一行,添加逗号 + if i + 16 < len(bytes_data): + c_array += "," + c_array += "\n" + + c_array += "};\n\n" + c_array += f"unsigned int {array_name}_size = {len(bytes_data)};\n" + + # 写入文件 + try: + with open(output_file, 'w', encoding='utf-8') as f: + f.write(c_array) + print(f"成功生成C数组文件: {output_file}") + print(f"数组名称: {array_name}") + print(f"数组大小: {len(bytes_data)} 字节") + return True + except Exception as e: + print(f"写入文件时出错: {e}") + return False +def hex_to_bin(hex_string, output_file="output.bin"): + """ + 将十六进制字符串转换为 bin 数据,并写入文件 + + Args: + hex_string (str): 十六进制字符串,可以包含空格或0x前缀 + output_file (str): 输出文件名 + """ + # 清理十六进制字符串,移除空格和0x前缀 + hex_clean = hex_string.replace(" ", "").replace("0x", "").replace("0X", "") + + # 验证十六进制字符串 + try: + # 转换为字节数组 + bytes_data = bytes.fromhex(hex_clean) + except ValueError as e: + print(f"错误:无效的十六进制字符串 - {e}") + return False + + # 写入文件 + try: + with open(output_file, 'wb') as f: + f.write(bytes_data) + print(f"成功生成 bin 文件: {output_file}") + return True + except Exception as e: + print(f"写入文件时出错: {e}") + return False 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""" - + hex_data = "" + hex_data2 = "" + with open('data1.hex', 'r', encoding='utf-8') as f: + hex = f.read() # bytes + hex_data = hex.replace(" ", "").replace("0x", "").replace("0X", "").replace("\n", "").replace("\r", "") + # print(hex_data) # 若需要转为 str + + with open('data2.hex', 'r', encoding='utf-8') as f: + hex2 = f.read() # bytes + hex_data2 = hex2.replace(" ", "").replace("0x", "").replace("0X", "").replace("\n", "").replace("\r", "") + # print(hex_data2) + hex_to_c_array(hex_data,"data1","data1.c") + hex_to_c_array(hex_data2,"data2","data2.c") + hex_to_bin(hex_data,"data1.bin") + hex_to_bin(hex_data2,"data2.bin") # 转换为字节 data = hex_to_bytes(hex_data) - + data2 = hex_to_bytes(hex_data2) + print("data size:{}".format(len(data))) + print("data2 size:{}".format(len(data2))) + datasum = data + data2 + print("datasum size:{}".format(len(datasum))) # 分析帧 - frames = analyze_websocket_frames(data) - + frames = analyze_websocket_frames(datasum) # 生成输出 output = { "summary": { @@ -181,11 +244,10 @@ def main(): 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]): + for i, frame in enumerate(frames): print(f"\n帧 {i+1}:") print(f" 偏移: {frame['offset']}") print(f" 大小: {frame['frame_size']} 字节") @@ -196,5 +258,8 @@ def main(): if frame['payload_json']: print(f" JSON内容: {frame['payload_json']}") + print("============================================") + print(f"分析完成,共发现 {len(frames)} 个有效WebSocket帧") + print("结果已保存到 websocket_simple_analysis.json") if __name__ == "__main__": main() \ No newline at end of file diff --git a/test_ws_parser/websocket_test b/test_ws_parser/websocket_test new file mode 100644 index 0000000000000000000000000000000000000000..2ddbef6049264f9838ffcf68b8bc6b060d0110c7 GIT binary patch literal 26480 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 IELG)S0alf>pa1{> literal 0 HcmV?d00001 -- 2.17.1