@@ -372,6 +372,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
372372 const char * silence_var ;
373373 int silence_val = 0 , bypass_media_after_bridge = 0 ;
374374 const char * bridge_answer_timeout = NULL ;
375+ const char * abs_answer_timeout = NULL ;
375376 int bridge_filter_dtmf , answer_timeout , sent_update = 0 ;
376377 time_t answer_limit = 0 ;
377378 const char * exec_app = NULL ;
@@ -425,6 +426,45 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
425426 }
426427 }
427428
429+ /* absolute_answer_timeout: compute the answer deadline relative to the originate
430+ * start time, so that the timeout covers the entire INVITE -> 200 OK window and
431+ * is not extended by 180/183 early media. When both bridge_answer_timeout and
432+ * absolute_answer_timeout are present, the earlier deadline wins.
433+ * absolute_answer_timeout: 基于 originate 开始时刻计算应答截止时间,使超时
434+ * 覆盖从 INVITE 到 200 OK 的整个窗口,不会被 180/183 早期媒体延长。当
435+ * bridge_answer_timeout 与 absolute_answer_timeout 同时存在时,以更早到期者为准。 */
436+ if (!switch_channel_test_flag (chan_a , CF_ANSWERED ) &&
437+ (abs_answer_timeout = switch_channel_get_variable (chan_a , "absolute_answer_timeout" ))) {
438+ int abs_timeout = atoi (abs_answer_timeout );
439+ if (abs_timeout > 0 ) {
440+ const char * start_epoch_str = switch_channel_get_variable (chan_a , "originate_start_epoch" );
441+ time_t start_epoch = 0 ;
442+
443+ if (!zstr (start_epoch_str )) {
444+ start_epoch = (time_t ) atol (start_epoch_str );
445+ }
446+ /* Fall back to "now" if the originate start was not recorded (e.g. the
447+ * caller channel was bridged from a path that did not go through
448+ * switch_ivr_originate). This degrades gracefully to bridge-loop relative.
449+ * 若未记录 originate 开始时间(例如未经 switch_ivr_originate 进入 bridge),
450+ * 退化为以当前时刻为起点,保证功能可用。 */
451+ if (start_epoch == 0 ) {
452+ start_epoch = switch_epoch_time_now (NULL );
453+ }
454+
455+ {
456+ time_t abs_limit = start_epoch + abs_timeout ;
457+
458+ if (answer_limit == 0 || abs_limit < answer_limit ) {
459+ answer_limit = abs_limit ;
460+ switch_log_printf (SWITCH_CHANNEL_SESSION_LOG (session_a ), SWITCH_LOG_DEBUG ,
461+ "Absolute answer timeout set to %d seconds from originate start on %s.\n" ,
462+ abs_timeout , switch_channel_get_name (chan_a ));
463+ }
464+ }
465+ }
466+ }
467+
428468 switch_channel_clear_flag (chan_a , CF_INTERCEPT );
429469 switch_channel_clear_flag (chan_a , CF_INTERCEPTED );
430470
0 commit comments