@@ -972,6 +972,15 @@ static esp_err_t esp_websocket_client_recv(esp_websocket_client_handle_t client)
972972 esp_websocket_free_buf (client , false);
973973 esp_tls_error_handle_t error_handle = esp_transport_get_error_handle (client -> transport );
974974 if (error_handle ) {
975+ // Check for specific transport error codes
976+ if (error_handle -> last_error == ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT ) {
977+ ESP_LOGV (TAG , "Transport layer reported timeout during read" );
978+ return ESP_OK ; // Treat timeout as OK, not an error
979+ } else if (error_handle -> last_error == ESP_ERR_ESP_TLS_TCP_CLOSED_FIN ) {
980+ ESP_LOGD (TAG , "Connection closed by peer (FIN)" );
981+ esp_websocket_client_abort_connection (client , WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT );
982+ return ESP_FAIL ;
983+ }
975984 esp_websocket_client_error (client , "esp_transport_read() failed with %d, transport_error=%s, tls_error_code=%i, tls_flags=%i, errno=%d" ,
976985 rlen , esp_err_to_name (error_handle -> last_error ), error_handle -> esp_tls_error_code ,
977986 error_handle -> esp_tls_flags , errno );
@@ -984,10 +993,50 @@ static esp_err_t esp_websocket_client_recv(esp_websocket_client_handle_t client)
984993 client -> last_fin = esp_transport_ws_get_fin_flag (client -> transport );
985994 client -> last_opcode = esp_transport_ws_get_read_opcode (client -> transport );
986995
987- if (rlen == 0 && client -> last_opcode == WS_TRANSPORT_OPCODES_NONE ) {
988- ESP_LOGV (TAG , "esp_transport_read timeouts" );
996+ // Enhanced timeout detection: Use transport layer error codes to distinguish timeout from valid empty message
997+ if (rlen == 0 ) {
998+ // Check transport layer error codes to determine if this is a timeout
999+ esp_tls_error_handle_t error_handle = esp_transport_get_error_handle (client -> transport );
1000+ bool is_timeout = false;
1001+
1002+ if (error_handle ) {
1003+ // Check for specific transport error codes that indicate timeout
1004+ if (error_handle -> last_error == ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT ) {
1005+ is_timeout = true;
1006+ ESP_LOGV (TAG , "Transport layer reported timeout (ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT)" );
1007+ }
1008+ }
1009+
1010+ // Fallback: Check WebSocket frame state for timeout indicators
1011+ if (!is_timeout ) {
1012+ // Condition 1: No opcode set (transport layer indicates no frame received)
1013+ if (client -> last_opcode == WS_TRANSPORT_OPCODES_NONE ) {
1014+ is_timeout = true;
1015+ ESP_LOGV (TAG , "No opcode set, treating as timeout" );
1016+ }
1017+ // Condition 2: Check if we're in a fragmented message state but got no data
1018+ else if (client -> payload_offset > 0 && client -> payload_len > 0 && client -> payload_offset < client -> payload_len ) {
1019+ // We're expecting more data for a fragmented message but got nothing
1020+ is_timeout = true;
1021+ ESP_LOGV (TAG , "Fragmented message timeout (offset=%d, payload_len=%d)" ,
1022+ client -> payload_offset , client -> payload_len );
1023+ }
1024+ }
1025+
1026+ if (is_timeout ) {
1027+ ESP_LOGV (TAG , "esp_transport_read timeout detected (rlen=%d, opcode=%d, payload_len=%d, offset=%d)" ,
1028+ rlen , client -> last_opcode , client -> payload_len , client -> payload_offset );
1029+ esp_websocket_free_buf (client , false);
1030+ return ESP_OK ;
1031+ }
1032+ }
1033+
1034+ // Additional validation: Check for invalid opcodes that might indicate corruption
1035+ if (rlen > 0 && client -> last_opcode > 0xF ) {
1036+ ESP_LOGW (TAG , "Received invalid WebSocket opcode: %d (max valid is 15)" , client -> last_opcode );
9891037 esp_websocket_free_buf (client , false);
990- return ESP_OK ;
1038+ esp_websocket_client_error (client , "Invalid WebSocket opcode received: %d" , client -> last_opcode );
1039+ return ESP_FAIL ;
9911040 }
9921041
9931042 esp_websocket_client_dispatch_event (client , WEBSOCKET_EVENT_DATA , client -> rx_buffer , rlen );
@@ -1015,6 +1064,12 @@ static esp_err_t esp_websocket_client_recv(esp_websocket_client_handle_t client)
10151064 } else if (client -> last_opcode == WS_TRANSPORT_OPCODES_CLOSE ) {
10161065 ESP_LOGD (TAG , "Received close frame" );
10171066 client -> state = WEBSOCKET_STATE_CLOSING ;
1067+ } else if (client -> last_opcode > 0xF ) {
1068+ // Invalid opcode detected - this indicates potential state corruption
1069+ ESP_LOGW (TAG , "Invalid opcode %d detected, resetting client state" , client -> last_opcode );
1070+ esp_websocket_free_buf (client , false);
1071+ esp_websocket_client_error (client , "Invalid WebSocket opcode %d - potential state corruption" , client -> last_opcode );
1072+ return ESP_FAIL ;
10181073 }
10191074 esp_websocket_free_buf (client , false);
10201075 return ESP_OK ;
0 commit comments