@@ -323,20 +323,58 @@ static void esp_websocket_event_handler(void *handler_args, esp_event_base_t bas
323323
324324 case WEBSOCKET_EVENT_DISCONNECTED :
325325 ESP_LOGI (TAG , "WEBSOCKET_EVENT_DISCONNECTED" );
326+
327+ BOOL connected = FALSE;
328+ STATUS retStatus = STATUS_SUCCESS ;
329+
326330 MUTEX_LOCK (pEspWrapper -> wsClientLock );
331+ connected = pEspWrapper -> isConnected ;
327332 pEspWrapper -> isConnected = FALSE;
328333 MUTEX_UNLOCK (pEspWrapper -> wsClientLock );
329334
335+ // Now DISCONNECT is the primary event for handling connection cleanup and reconnection
336+ BOOL wasConnected = connected ;
330337 ATOMIC_STORE_BOOL (& pSignalingClient -> connected , FALSE);
331- if ((SERVICE_CALL_RESULT ) ATOMIC_LOAD (& pSignalingClient -> result ) == SERVICE_CALL_RESULT_NOT_SET ) {
332- ATOMIC_STORE (& pSignalingClient -> result , (SIZE_T ) SERVICE_CALL_UNKNOWN );
333- }
334338
335- // Signal the condition variable to wake up the waiting thread
339+ // Signal condition variables to wake up waiting threads
336340 MUTEX_LOCK (pSignalingClient -> connectedLock );
337341 CVAR_SIGNAL (pSignalingClient -> connectedCvar );
338342 MUTEX_UNLOCK (pSignalingClient -> connectedLock );
339343
344+ CVAR_BROADCAST (pSignalingClient -> receiveCvar );
345+ CVAR_BROADCAST (pSignalingClient -> sendCvar );
346+ ATOMIC_STORE (& pSignalingClient -> messageResult , (SIZE_T ) SERVICE_CALL_RESULT_OK );
347+
348+ // Handle reconnection logic
349+ if (wasConnected && ATOMIC_LOAD (& pSignalingClient -> result ) != SERVICE_CALL_RESULT_SIGNALING_RECONNECT_ICE &&
350+ !ATOMIC_LOAD_BOOL (& pSignalingClient -> shutdown )) {
351+
352+ ESP_LOGI (TAG , "WebSocket disconnected from active connection, triggering reconnection via error callback" );
353+
354+ // Set the result failed to indicate disconnection
355+ ATOMIC_STORE (& pSignalingClient -> result , (SIZE_T ) SERVICE_CALL_UNKNOWN );
356+
357+ // Use the existing error callback mechanism to trigger reconnection
358+ if (pSignalingClient -> signalingClientCallbacks .errorReportFn != NULL ) {
359+ CHAR errorMsg [] = "WebSocket connection lost, triggering reconnection" ;
360+ ESP_LOGI (TAG , "DEBUG: Calling errorReportFn with STATUS_SIGNALING_RECONNECT_FAILED=0x%08x" , STATUS_SIGNALING_RECONNECT_FAILED );
361+ pSignalingClient -> signalingClientCallbacks .errorReportFn (
362+ pSignalingClient -> signalingClientCallbacks .customData ,
363+ STATUS_SIGNALING_RECONNECT_FAILED ,
364+ errorMsg ,
365+ (UINT32 ) STRLEN (errorMsg ));
366+ ESP_LOGI (TAG , "Signaled for reconnection via error callback" );
367+ } else {
368+ ESP_LOGW (TAG , "No error callback registered, cannot signal for reconnection" );
369+ }
370+ } else if (!wasConnected ) {
371+ ESP_LOGI (TAG , "WebSocket disconnected but was not previously connected, not triggering reconnection" );
372+ } else if (ATOMIC_LOAD_BOOL (& pSignalingClient -> shutdown )) {
373+ ESP_LOGI (TAG , "WebSocket disconnected during shutdown, not triggering reconnection" );
374+ } else {
375+ ESP_LOGI (TAG , "WebSocket disconnected during ICE reconnect, not triggering full reconnection" );
376+ }
377+
340378 // Free the WebSocket buffer on disconnect
341379 freeWebSocketBuffer ();
342380 break ;
@@ -400,20 +438,19 @@ static void esp_websocket_event_handler(void *handler_args, esp_event_base_t bas
400438 }
401439 }
402440
441+ // For ERROR events, just log and wake up waiting threads
442+ // Let DISCONNECT event handle all state changes and reconnection logic
403443 if (pSignalingClient != NULL ) {
404- ATOMIC_STORE_BOOL (& pSignalingClient -> connected , FALSE);
405- // Set result if not already set
406- if ((SERVICE_CALL_RESULT ) ATOMIC_LOAD (& pSignalingClient -> result ) == SERVICE_CALL_RESULT_NOT_SET ) {
407- ATOMIC_STORE (& pSignalingClient -> result , (SIZE_T ) SERVICE_CALL_UNKNOWN );
408-
409- // Signal the waiting thread about the error
410- // The mutex must be locked before signaling
411- MUTEX_LOCK (pSignalingClient -> connectedLock );
412- CVAR_SIGNAL (pSignalingClient -> connectedCvar );
413- MUTEX_UNLOCK (pSignalingClient -> connectedLock );
414- }
415- // Reset the buffer on error
416- resetWebSocketBuffer ();
444+ ESP_LOGI (TAG , "WebSocket error occurred, waiting for disconnect event to handle cleanup and reconnection" );
445+
446+ // Signal condition variables to wake up waiting threads
447+ MUTEX_LOCK (pSignalingClient -> connectedLock );
448+ CVAR_SIGNAL (pSignalingClient -> connectedCvar );
449+ MUTEX_UNLOCK (pSignalingClient -> connectedLock );
450+
451+ CVAR_BROADCAST (pSignalingClient -> receiveCvar );
452+ CVAR_BROADCAST (pSignalingClient -> sendCvar );
453+ ATOMIC_STORE (& pSignalingClient -> messageResult , (SIZE_T ) SERVICE_CALL_RESULT_OK );
417454 } else {
418455 ESP_LOGW (TAG , "pSignalingClient is NULL in WEBSOCKET_EVENT_ERROR!" );
419456 }
@@ -920,18 +957,16 @@ STATUS connectEspSignalingClient(PSignalingClient pSignalingClient)
920957 // Set ping interval to match SIGNALING_SERVICE_WSS_PING_PONG_INTERVAL_IN_SECONDS (10 seconds)
921958 ws_cfg .ping_interval_sec = 10 ;
922959
923- // Enable auto reconnect to handle network issues gracefully
924- ws_cfg .disable_auto_reconnect = FALSE;
960+ // Disable auto reconnect to let the state machine handle reconnection with fresh credentials
961+ // Auto-reconnect would fail after 5 minutes when the signed URL expires
962+ ws_cfg .disable_auto_reconnect = TRUE;
925963
926964 // Set reconnect timeout to match ESP-IDF recommendations
927965 ws_cfg .reconnect_timeout_ms = 10000 ; // 10 seconds
928966
929967 // Configure TCP keepalive to match SIGNALING_SERVICE_TCP_KEEPALIVE settings
930968 ws_cfg .network_timeout_ms = SIGNALING_SERVICE_TCP_KEEPALIVE_IN_SECONDS * 1000 ;
931969
932- // Configure transport - since we're using wss:// in the URL, this will automatically be SSL
933- // ws_cfg.transport = WEBSOCKET_TRANSPORT_OVER_SSL;
934-
935970 // For development, set skip_cert_common_name_check to true to skip cert verification
936971 // In production environments, this should be set to false
937972#ifdef CONFIG_SKIP_COMMON_NAME_CHECK
0 commit comments