diff --git a/docs/voice_diagnostics.md b/docs/voice_diagnostics.md index 0c4e6a4..1a67a90 100644 --- a/docs/voice_diagnostics.md +++ b/docs/voice_diagnostics.md @@ -33,3 +33,32 @@ `inc/app_gnss_log.h` 中的 `APP_GNSS_LOG_ENABLED` 默认是 `0`,关闭应用侧全部 GNSS/NMEA 原始输出、解析失败、模式切换、卫星搜索、坐标打印和 GPS 查询提示。需要恢复时可在编译参数中设置 `-DAPP_GNSS_LOG_ENABLED=1`。语音与 NITZ 时间校准诊断继续输出。 GNSS 数据解析、定位上报和硬件开关流程继续运行。原先放在打印参数内的四处 `ql_gnss_close()` 已分离为独立操作,避免禁用日志时跳过关闭定位。`python3 tools/test_gnss_logging.py` 在日志开启和关闭两种配置下验证真实解析代码、无卫星退出、卫星不足退出、搜索超时退出及 FAST 切换 SLOW 的关闭路径。 + +## 连接失败与提示音诊断 + +`WSS-DIAG` 使用 `stage` 区分 TLS 握手、TLS 读取、WebSocket 升级。日志记录阶段、实际耗时、超时配置、错误码和收包情况,不输出原始响应头、Cookie 或音频内容。TLS 握手仍是 20 秒总窗口,WebSocket 升级仍是 10 秒窗口,HTTP select 等待仍是 2 秒。 + +| 日志字段 | 含义和排查方向 | +| --- | --- | +| `stage=tls_handshake result=timeout phase=server hello` | TLS 等待服务器 Hello 超时,不能据此判断证书错误。结合 `last_step`、`want_read`/`want_write`、`phase_ms`、`calls_ms` 判断等待和本地计算耗时 | +| `stage=tls_connect failed_at=… verify_flags=…` | 记录 TLS 初始化/建连的失败步骤和证书校验标志;校验标志仅在已进行证书校验时有解释意义 | +| `stage=tls_read reason=peer_close_notify` | 对端发送 TLS 关闭通知;仅证明关闭由对端通知,不证明为何关闭 | +| `stage=tls_read reason=tls_eof/tls_read_timeout/tls_read_error` | 分别表示读取返回 0、TLS 读取超时、其他读取错误;保留原始十进制和十六进制返回值 | +| `stage=ws_upgrade reason=no_response_timeout` | 升级等待超时,缓冲中没有响应数据;对照 `rx_bytes=0`,服务端需核查请求是否到达及是否返回 101 | +| `stage=ws_upgrade reason=incomplete_headers_timeout` | 收到部分数据,但在窗口内未收到完整 HTTP 响应头 | +| `stage=ws_upgrade reason=http_rejected http=…` | 收到了完整响应头及非 101 状态;按实际 HTTP 状态检查代理或后端 | +| `stage=ws_upgrade reason=invalid_upgrade_response` | 收到非法或不符合 WebSocket 校验的响应;例如 101 响应的 Accept/Upgrade/Connection 不符合要求,或响应格式错误;当前不进一步细分具体头字段 | +| `stage=ws_upgrade reason=transport_error` | 等待升级期间底层连接出错,结合紧邻的 `tls_read` 日志及断开回调的具体错误描述 | +| `HTTP-DIAG stage=tcp_connect/response_header/response_body` | HTTP 在建连、响应头或响应体等待期间失败;`timeout` 表示 select 返回 0,`select_error` 表示负值,并记录立即保存的 errno;超时的 errno 字段为 0,不能用历史 errno 推断原因 | +| `NET-GATE leave recording=… pending=… mqtt=… action=…` | 记录留言键为什么被拦截,区分正在录音、等待留言请求回复和 MQTT 离线。忙碌分支当前仍播放原有网络提示并清除 pending,此次仅增加诊断 | +| `NET-GATE tip=network_ok reason=mqtt_connected voice_service=not_checked` | “已连上网络”仅由 MQTT 连通触发,不表示 TLS/WebSocket/语音业务已验证 | + +例如此次无响应升级会输出类似以下摘要(示例,并非当前固件已有的历史日志): + +```text +[WSS-DIAG] stage=ws_upgrade result=failed reason=no_response_timeout http=0 elapsed_ms=10000 timeout_ms=10000 rx_bytes=0 buffered=0 header_bytes=0 parser=0 polls=... +``` + +`http=0` 表示尚未解析到有效状态码,不是服务器返回的 HTTP 状态码。成功 TLS 写入只证明本地传输层接受了数据,设备端仍不能独自证明请求到达服务器或定位中间链路丢包。诊断不会改变现有提示音、重试或业务状态机。 + +验证:`python3 tools/test_wss_receive.py` 覆盖完整/分段 101、零响应超时、部分响应头超时、503 拒绝、非法 Accept、对端关闭、TLS 读取超时等分支;`python3 tools/test_wss_handshake.py` 验证真实握手函数的超时/失败摘要及原有时限、重试和 tick 回绕。以上为主机侧函数测试,需重新构建并烧录目标固件后采集新日志。 diff --git a/ql-application/threadx/interface/custom_app/hal_key.c b/ql-application/threadx/interface/custom_app/hal_key.c index 8eb650d..4afc98e 100644 --- a/ql-application/threadx/interface/custom_app/hal_key.c +++ b/ql-application/threadx/interface/custom_app/hal_key.c @@ -168,6 +168,7 @@ static void key_thread_entry(void *parameter) !mic_pdp ? "blocked_no_pdp" : (mic_mqtt != 1 ? "blocked_mqtt_offline" : "start_voice")); if(mic_pdp && mic_mqtt == 1){ if(tts_play_interrupt_func()==-2){ + printf("[NET-GATE] mic tip=network_check reason=voice_connect_failed pdp=%d mqtt=%d\r\n", mic_pdp, mic_mqtt); app_play_tips_file(2); } }else{ @@ -213,7 +214,14 @@ static void key_thread_entry(void *parameter) build_alarm(); } else if(ql_rtos_get_systicks() - key_press_alarm_time > KEY_WAIT_TIME){ - if(!vad_audio_is_recording()&&key_start_leave==0&&get_mqtt_connect_status()==1){ + int leave_recording = vad_audio_is_recording(); + int leave_mqtt = get_mqtt_connect_status(); + printf("[NET-GATE] leave recording=%d pending=%d mqtt=%d action=%s\r\n", + leave_recording, key_start_leave, leave_mqtt, + leave_recording ? "blocked_recording" : + (key_start_leave ? "blocked_pending" : + (leave_mqtt != 1 ? "blocked_mqtt_offline" : "request_leave"))); + if(!leave_recording&&key_start_leave==0&&leave_mqtt==1){ key_start_leave = 1; build_leave_to_parent(); }else{ diff --git a/ql-application/threadx/interface/custom_app/lib/librws/src/rws_socketpriv.c b/ql-application/threadx/interface/custom_app/lib/librws/src/rws_socketpriv.c index 9010aa0..d244e2a 100644 --- a/ql-application/threadx/interface/custom_app/lib/librws/src/rws_socketpriv.c +++ b/ql-application/threadx/interface/custom_app/lib/librws/src/rws_socketpriv.c @@ -340,8 +340,13 @@ rws_bool rws_socket_recv(_rws_socket *s) break; } if (len <= 0) { - LOG_E("WSS TLS peer closed or read failed: %d\n", len); - s->error = rws_error_new_code_descr(rws_error_code_read_write_socket, "TLS peer closed or read failed"); + const char *reason = len == 0 ? "tls_eof" : + (len == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ? "peer_close_notify" : + (len == MBEDTLS_ERR_SSL_TIMEOUT ? "tls_read_timeout" : "tls_read_error")); + printf("[WSS-DIAG] stage=tls_read reason=%s ret=%d hex=-0x%04x command=%d rx_bytes=%u buffered=%u\n", + reason, len, (unsigned int)-len, s->command, + s->diag_rx_bytes, (unsigned int)s->received_len); + s->error = rws_error_new_code_descr(rws_error_code_read_write_socket, reason); s->command = COMMAND_INFORM_DISCONNECTED; result = rws_false; goto _exit; @@ -1032,10 +1037,14 @@ void rws_socket_idle_send(_rws_socket *s) void rws_socket_wait_handshake_responce(_rws_socket *s) { - unsigned int started = ql_rtos_get_systicks(); + unsigned int started = ql_rtos_get_systicks(), polls = 0; + unsigned int rx_before = s->diag_rx_bytes; size_t header_length = 0; int status = 0, result = 0; + const char *reason; + printf("[WSS-DIAG] stage=ws_upgrade event=begin timeout_ms=10000\n"); while (result == 0) { + ++polls; rws_socket_recv(s); if (s->error) break; result = rws_check_handshake((const char *)s->received, s->received_len, @@ -1045,6 +1054,9 @@ void rws_socket_wait_handshake_responce(_rws_socket *s) rws_thread_sleep(10); } if (result == 1 && !s->error) { + printf("[WSS-DIAG] stage=ws_upgrade result=ok http=101 elapsed_ms=%u rx_bytes=%u header_bytes=%u polls=%u\n", + (unsigned int)(ql_rtos_get_systicks() - started) * 5, + s->diag_rx_bytes - rx_before, (unsigned int)header_length, polls); s->received_len -= header_length; if (s->received_len) memmove(s->received, (char *)s->received + header_length, s->received_len); @@ -1052,10 +1064,15 @@ void rws_socket_wait_handshake_responce(_rws_socket *s) s->command = COMMAND_INFORM_CONNECTED; LOG_I("WebSocket upgrade verified: HTTP 101\n"); } else { - LOG_E("WebSocket upgrade failed: HTTP %d (0 means incomplete/invalid headers)\n", status); + reason = s->error ? "transport_error" : + (result == 0 ? (s->received_len ? "incomplete_headers_timeout" : "no_response_timeout") : + (status && status != 101 ? "http_rejected" : "invalid_upgrade_response")); + printf("[WSS-DIAG] stage=ws_upgrade result=failed reason=%s http=%d elapsed_ms=%u timeout_ms=10000 rx_bytes=%u buffered=%u header_bytes=%u parser=%d polls=%u\n", + reason, status, (unsigned int)(ql_rtos_get_systicks() - started) * 5, + s->diag_rx_bytes - rx_before, (unsigned int)s->received_len, + (unsigned int)header_length, result, polls); if (!s->error) - s->error = rws_error_new_code_descr(rws_error_code_parse_handshake, - "Invalid or timed out WebSocket upgrade"); + s->error = rws_error_new_code_descr(rws_error_code_parse_handshake, reason); rws_socket_close(s); s->command = COMMAND_INFORM_DISCONNECTED; } @@ -1905,6 +1922,19 @@ static const char *rws_tls_phase_name(int state) case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: return "server key exchange"; case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: return "client key exchange"; case MBEDTLS_SSL_SERVER_FINISHED: return "server finished"; + case MBEDTLS_SSL_HELLO_REQUEST: return "hello request"; + case MBEDTLS_SSL_CERTIFICATE_REQUEST: return "certificate request"; + case MBEDTLS_SSL_SERVER_HELLO_DONE: return "server hello done"; + case MBEDTLS_SSL_CLIENT_CERTIFICATE: return "client certificate"; + case MBEDTLS_SSL_CERTIFICATE_VERIFY: return "certificate verify"; + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: return "client change cipher spec"; + case MBEDTLS_SSL_CLIENT_FINISHED: return "client finished"; + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: return "server change cipher spec"; + case MBEDTLS_SSL_FLUSH_BUFFERS: return "flush buffers"; + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: return "handshake wrapup"; + case MBEDTLS_SSL_HANDSHAKE_OVER: return "handshake over"; + case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: return "server new session ticket"; + case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: return "server hello verify request sent"; default: return "other"; } } @@ -1913,10 +1943,14 @@ static int rws_tls_handshake_timed(mbedtls_ssl_context *ctx) { unsigned int started = ql_rtos_get_systicks(); unsigned int phase_started = started, call_ticks = 0, retries = 0; - int state = ctx->state, ret = 0; + int state = ctx->state, ret = 0, last_step_ret = 0; + unsigned int want_read = 0, want_write = 0; while (ctx->state != MBEDTLS_SSL_HANDSHAKE_OVER) { unsigned int before = ql_rtos_get_systicks(); ret = mbedtls_ssl_handshake_step(ctx); + last_step_ret = ret; + if (ret == MBEDTLS_ERR_SSL_WANT_READ) ++want_read; + if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ++want_write; call_ticks += (unsigned int)(ql_rtos_get_systicks() - before); if (ret != 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) break; @@ -1946,6 +1980,12 @@ static int rws_tls_handshake_timed(mbedtls_ssl_context *ctx) } LOG_I("WSS TLS handshake total=%u ms, state=%d, ret=%d\n", (unsigned int)(ql_rtos_get_systicks() - started) * 5, ctx->state, ret); + LOG_I("[WSS-DIAG] stage=tls_handshake result=%s phase=%s state=%d elapsed_ms=%u timeout_ms=20000 ret=%d hex=-0x%04x last_step=%d want_read=%u want_write=%u phase_ms=%u calls_ms=%u\n", + ret == 0 ? "ok" : (ret == MBEDTLS_ERR_SSL_TIMEOUT ? "timeout" : "failed"), + rws_tls_phase_name(ctx->state), ctx->state, + (unsigned int)(ql_rtos_get_systicks() - started) * 5, ret, (unsigned int)-ret, + last_step_ret, want_read, want_write, + (unsigned int)(ql_rtos_get_systicks() - phase_started) * 5, call_ticks * 5); return ret; } @@ -2037,7 +2077,13 @@ int rws_ssl_conn(_rws_socket *s) exit: LOG_E("WSS TLS connection failed at %s: %d (-0x%04x)\n", stage, ret, (unsigned int)-ret); rws_error_delete_clean(&s->error); - s->error = rws_error_new_code_descr(rws_error_code_connect_to_host, "TLS connection or certificate verification failed"); + if (s->ssl) + LOG_E("[WSS-DIAG] stage=tls_connect failed_at=%s ret=%d verify_flags=0x%08lx\n", + stage, ret, (unsigned long)mbedtls_ssl_get_verify_result(&s->ssl->ssl_ctx)); + s->error = rws_error_new_code_descr(rws_error_code_connect_to_host, + ret == MBEDTLS_ERR_SSL_TIMEOUT ? "TLS handshake timeout" : + (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ? "TLS certificate verification failed" : + "TLS connection setup or handshake failed")); if (s->ssl) { /* Do not send close_notify for an incomplete handshake. */ mbedtls_net_free(&s->ssl->net_ctx); diff --git a/ql-application/threadx/interface/custom_app/lib/webclient/webclient.c b/ql-application/threadx/interface/custom_app/lib/webclient/webclient.c index 729990f..700f1b9 100644 --- a/ql-application/threadx/interface/custom_app/lib/webclient/webclient.c +++ b/ql-application/threadx/interface/custom_app/lib/webclient/webclient.c @@ -17,7 +17,8 @@ #include #include #include -#include +#include +#include #include #include @@ -131,12 +132,14 @@ static int webclient_read_line(struct webclient_session *session, char *buffer, FD_SET(session->socket, &read_fds); ret = select(session->socket + 1, &read_fds, NULL, NULL, &t); + int select_errno = ret < 0 ? errno : 0; // printf("select ret: %d\r\n", ret); if(ret <= 0) { - printf("*** select timeout or error ***\r\n"); + printf("[HTTP-DIAG] stage=response_header reason=%s select_ret=%d errno_snapshot=%d timeout_ms=2000\r\n", + ret == 0 ? "timeout" : "select_error", ret, select_errno); return -WEBCLIENT_ERROR; } @@ -561,12 +564,14 @@ static int webclient_connect(struct webclient_session *session, const char *URI) FD_SET(socket_handle, &write_fds); rc= select(socket_handle + 1, &read_fds, &write_fds, NULL, &t); + int select_errno = rc < 0 ? errno : 0; printf("select ret: %d\r\n", rc); if(rc <= 0) { - printf("*** select timeout or error ***\r\n"); + printf("[HTTP-DIAG] stage=tcp_connect reason=%s select_ret=%d errno_snapshot=%d timeout_ms=2000\r\n", + rc == 0 ? "timeout" : "select_error", rc, select_errno); rc = -WEBCLIENT_CONNECT_FAILED; goto __exit; } @@ -1376,12 +1381,14 @@ int webclient_read(struct webclient_session *session, void *buffer, size_t lengt FD_SET(session->socket, &read_fds); ret = select(session->socket + 1, &read_fds, NULL, NULL, &t); + int select_errno = ret < 0 ? errno : 0; // printf("select ret: %d\r\n", ret); if(ret <= 0) { - printf("*** select timeout or error ***\r\n"); + printf("[HTTP-DIAG] stage=response_body reason=%s select_ret=%d errno_snapshot=%d timeout_ms=2000\r\n", + ret == 0 ? "timeout" : "select_error", ret, select_errno); return -WEBCLIENT_ERROR; } diff --git a/ql-application/threadx/interface/custom_app/mqtt.c b/ql-application/threadx/interface/custom_app/mqtt.c index 5f3f410..0475bdf 100644 --- a/ql-application/threadx/interface/custom_app/mqtt.c +++ b/ql-application/threadx/interface/custom_app/mqtt.c @@ -821,6 +821,7 @@ int app_mqtt_connect() MQTT_CONN_UNLOCK(); // [ADD] 连接成功提示音 + printf("[NET-GATE] tip=network_ok reason=mqtt_connected voice_service=not_checked\r\n"); app_play_tips_file(11); if(ret!=0){ diff --git a/tools/test_wss_handshake.py b/tools/test_wss_handshake.py index 0affc45..a4c0dcc 100644 --- a/tools/test_wss_handshake.py +++ b/tools/test_wss_handshake.py @@ -1,6 +1,7 @@ """Test the actual timed handshake loop with scripted SDK steps and 5 ms ticks.""" from pathlib import Path import subprocess +import os root = Path(__file__).resolve().parents[1] source = (root / 'ql-application/threadx/interface/custom_app/lib/librws/src/rws_socketpriv.c').read_bytes().decode('latin1') @@ -15,7 +16,12 @@ typedef struct { int ret, next_state; unsigned int duration; } step; static step steps[16]; static int count, calls, sleeps; static unsigned int ticks; -static void test_log(const char *fmt, ...) { (void)fmt; } +static char diagnostic[1024]; +static void test_log(const char *fmt, ...) { + va_list args; + if (!strstr(fmt, "[WSS-DIAG]")) return; + va_start(args, fmt); vsnprintf(diagnostic, sizeof(diagnostic), fmt, args); va_end(args); +} #define LOG_I test_log static unsigned int ql_rtos_get_systicks(void) { return ticks; } static void rws_thread_sleep(unsigned int ms) { ticks += ms / 5; ++sleeps; } @@ -52,8 +58,11 @@ int main(void) { assert(rws_tls_handshake_timed(&ctx) == 0 && calls == 2 && sleeps == 0); reset(&ctx); steps[0] = (step){-99, MBEDTLS_SSL_SERVER_CERTIFICATE, 1}; count = 1; assert(rws_tls_handshake_timed(&ctx) == -99 && calls == 1 && sleeps == 0); - reset(&ctx); + assert(strstr(diagnostic, "result=failed phase=server certificate") && strstr(diagnostic, "ret=-99")); + reset(&ctx); ctx.state = MBEDTLS_SSL_SERVER_HELLO; assert(rws_tls_handshake_timed(&ctx) == MBEDTLS_ERR_SSL_TIMEOUT && ticks == 4000 && calls < 2100); + assert(strstr(diagnostic, "result=timeout phase=server hello") && strstr(diagnostic, "elapsed_ms=20000")); + assert(strstr(diagnostic, "last_step=-26880") && strstr(diagnostic, "want_write=0")); reset(&ctx); ticks = (unsigned int)-1000; assert(rws_tls_handshake_timed(&ctx) == MBEDTLS_ERR_SSL_TIMEOUT && calls < 2100); reset(&ctx); steps[0] = (step){0, MBEDTLS_SSL_SERVER_CERTIFICATE, 4001}; count = 1; @@ -69,7 +78,12 @@ output.mkdir(parents=True, exist_ok=True) cfile = output / 'test_wss_handshake.c' cfile.write_text(harness, encoding='utf-8') exe = output / 'test_wss_handshake.exe' -subprocess.run(['cl', '/nologo', '/W4', '/WX', '/TC', str(cfile), - '/I' + str(root / 'ql-application/threadx/common/include'), - '/Fo' + str(output / 'test_wss_handshake.obj'), '/Fe' + str(exe)], check=True) +if os.name == "nt": + subprocess.run(['cl', '/nologo', '/W4', '/WX', '/TC', str(cfile), + '/I' + str(root / 'ql-application/threadx/common/include'), + '/Fo' + str(output / 'test_wss_handshake.obj'), '/Fe' + str(exe)], check=True) +else: + subprocess.run(['cc', '-std=c99', '-Wall', '-Wextra', '-Werror', + '-I' + str(root / 'ql-application/threadx/common/include'), + str(cfile), '-o', str(exe)], check=True) subprocess.run([str(exe)], check=True) diff --git a/tools/test_wss_receive.py b/tools/test_wss_receive.py index cf0aa9f..d30c603 100644 --- a/tools/test_wss_receive.py +++ b/tools/test_wss_receive.py @@ -18,6 +18,8 @@ harness = r''' #define MBEDTLS_ERR_SSL_WANT_READ -2 #define MBEDTLS_ERR_SSL_WANT_WRITE -3 #define MBEDTLS_ERR_NET_RECV_FAILED -4 +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -30848 +#define MBEDTLS_ERR_SSL_TIMEOUT -26624 #define WSAEWOULDBLOCK 11 #define WSAEINPROGRESS 115 #define RWS_RECEIVE_BUFF_SIZE 1024 @@ -44,9 +46,10 @@ typedef struct { static int replies[16], reply_count, calls, closes; static size_t offset; static unsigned int ticks; -static const char response[] = +static const char good_response[] = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\n" "Connection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\nDATA"; +static const char *response = good_response; static unsigned int ql_rtos_get_systicks(void) { return ticks; } static void rws_thread_sleep(int ms) { ticks += (unsigned int)ms; } static void rws_error_delete_clean(const char **e) { *e = NULL; } @@ -64,7 +67,7 @@ static int mbedtls_ssl_read(int *ctx, unsigned char *buf, size_t size) { int ret = calls < reply_count ? replies[calls] : MBEDTLS_ERR_SSL_WANT_READ; (void)ctx; ++calls; if (ret > 0) { - assert((size_t)ret <= size && offset + (size_t)ret <= sizeof(response) - 1); + assert((size_t)ret <= size && offset + (size_t)ret <= strlen(response)); memcpy(buf, response + offset, (size_t)ret); offset += (size_t)ret; } return ret; @@ -78,7 +81,7 @@ static void reset(_rws_socket *s, tls *ctx) { s->expected_accept = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="; s->payload_buff = (char *)malloc(RWS_RECEIVE_BUFF_SIZE); assert(s->payload_buff); s->command = COMMAND_WAIT_HANDSHAKE_RESPONCE; - calls = closes = reply_count = 0; offset = 0; ticks = 0; + calls = closes = reply_count = 0; offset = 0; ticks = 0; response = good_response; } int main(void) { tls ctx = {0}; _rws_socket s = {0}; int want; @@ -86,7 +89,7 @@ int main(void) { reset(&s, &ctx); replies[0] = want; reply_count = 1; assert(!rws_socket_recv(&s)); assert(!s.error && s.command == COMMAND_WAIT_HANDSHAKE_RESPONCE && closes == 0); - replies[1] = 17; replies[2] = want; replies[3] = (int)sizeof(response) - 1 - 17; + replies[1] = 17; replies[2] = want; replies[3] = (int)strlen(response) - 17; reply_count = 4; rws_socket_wait_handshake_responce(&s); assert(s.is_connected && !s.error && s.command == COMMAND_INFORM_CONNECTED); @@ -96,6 +99,7 @@ int main(void) { reset(&s, &ctx); rws_socket_wait_handshake_responce(&s); assert(!s.is_connected && s.error && closes == 1 && ticks >= 2000 && calls < 300); + assert(!strcmp(s.error, "no_response_timeout")); free(s.payload_buff); reset(&s, &ctx); ticks = (unsigned int)-1000; rws_socket_wait_handshake_responce(&s); @@ -109,11 +113,25 @@ int main(void) { reset(&s, NULL); rws_socket_wait_handshake_responce(&s); assert(s.error && closes == 1 && calls == 0); free(s.payload_buff); reset(&s, &ctx); s.expected_accept = "wrong"; - replies[0] = (int)sizeof(response) - 1; reply_count = 1; + replies[0] = (int)strlen(response); reply_count = 1; rws_socket_wait_handshake_responce(&s); assert(!s.is_connected && s.error && closes == 1); free(s.payload_buff); + assert(!strcmp(s.error, "invalid_upgrade_response")); + reset(&s, &ctx); response = "HTTP/1.1 503 Service Unavailable\r\nContent-Length: 0\r\n\r\n"; + replies[0] = (int)strlen(response); reply_count = 1; + rws_socket_wait_handshake_responce(&s); + assert(!s.is_connected && closes == 1 && !strcmp(s.error, "http_rejected")); free(s.payload_buff); + reset(&s, &ctx); replies[0] = 17; reply_count = 1; + rws_socket_wait_handshake_responce(&s); + assert(!s.is_connected && closes == 1 && !strcmp(s.error, "incomplete_headers_timeout")); free(s.payload_buff); + reset(&s, &ctx); replies[0] = MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY; reply_count = 1; + rws_socket_wait_handshake_responce(&s); + assert(closes == 1 && !strcmp(s.error, "peer_close_notify")); free(s.payload_buff); + reset(&s, &ctx); replies[0] = MBEDTLS_ERR_SSL_TIMEOUT; reply_count = 1; + rws_socket_wait_handshake_responce(&s); + assert(closes == 1 && !strcmp(s.error, "tls_read_timeout")); free(s.payload_buff); free(s.received); - puts("PASS: actual TLS receive/upgrade loop: WANT_READ/WRITE, split HTTP 101, trailing frame bytes, timeout/wrap, EOF/fatal, null TLS, invalid Accept"); + puts("PASS: actual TLS receive/upgrade loop: WANT_READ/WRITE, split HTTP 101, trailing frame bytes, timeout/wrap, EOF/fatal, null TLS, invalid Accept, HTTP rejection, partial-header timeout, close_notify, TLS timeout"); return 0; } '''