diff --git a/conf/sofia.conf.xml b/conf/sofia.conf.xml index 6873c7d539..ea343ab29e 100644 --- a/conf/sofia.conf.xml +++ b/conf/sofia.conf.xml @@ -95,7 +95,8 @@ - + + diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 95614d6b2c..896c11bdb4 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -130,6 +130,8 @@ SWITCH_DECLARE(switch_rtp_t *) switch_rtp_new(const char *rx_host, */ SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, const char **err); +SWITCH_DECLARE(void) switch_rtp_set_max_missed_packets(switch_rtp_t *rtp_session, uint32_t max); + /*! \brief Assign a local address to the RTP session \param rtp_session an RTP session to assign the local address to diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index a1854f29bd..6458cbdcae 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -259,6 +259,7 @@ struct sofia_profile { time_t started; uint32_t session_timeout; uint32_t max_proceeding; + uint32_t rtp_timeout_sec; #ifdef SWITCH_HAVE_ODBC char *odbc_dsn; char *odbc_user; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 0356c8c049..1b27fc89d0 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -893,6 +893,11 @@ switch_status_t config_sofia(int reload, char *profile_name) if (v_max_proceeding >= 0) { profile->max_proceeding = v_max_proceeding; } + } else if (!strcasecmp(var, "rtp-timeout-sec")) { + int v = atoi(val); + if (v >= 0) { + profile->rtp_timeout_sec = v; + } } else if (!strcasecmp(var, "manage-presence")) { if (switch_true(val)) { profile->pflags |= PFLAG_PRESENCE; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index ace812c654..fde08516a7 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -937,6 +937,8 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f switch_rtp_flag_t flags; switch_status_t status; char tmp[50]; + uint32_t rtp_timeout_sec = tech_pvt->profile->rtp_timeout_sec; + assert(tech_pvt != NULL); @@ -1061,6 +1063,20 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f } + if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_timeout_sec"))) { + int v = atoi(val); + if (v >= 0) { + rtp_timeout_sec = v; + } + } + + if (rtp_timeout_sec) { + uint32_t packets; + packets = (tech_pvt->read_codec.implementation->samples_per_second * rtp_timeout_sec) / + tech_pvt->read_codec.implementation->samples_per_frame; + + switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, packets); + } if (tech_pvt->te) { switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te); diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 60f3ae8d4c..e0c554999c 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -168,6 +168,8 @@ struct switch_rtp { uint8_t cn; switch_time_t last_time; stfu_instance_t *jb; + uint32_t max_missed_packets; + uint32_t missed_count; }; static int global_init = 0; @@ -392,6 +394,11 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s return status; } +SWITCH_DECLARE(void) switch_rtp_set_max_missed_packets(switch_rtp_t *rtp_session, uint32_t max) +{ + rtp_session->max_missed_packets = max; +} + SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, const char **err) { *err = "Success"; @@ -897,6 +904,11 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (check) { do_2833(rtp_session); + if (!bytes && rtp_session->max_missed_packets) { + if (++rtp_session->missed_count >= rtp_session->max_missed_packets) { + return -1; + } + } if (rtp_session->jb && (jb_frame = stfu_n_read_a_frame(rtp_session->jb))) { memcpy(rtp_session->recv_msg.body, jb_frame->data, jb_frame->dlen); @@ -905,9 +917,9 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } bytes = jb_frame->dlen + rtp_header_len; rtp_session->recv_msg.header.ts = htonl(jb_frame->ts); - } else if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) { - uint8_t *data = (uint8_t *) rtp_session->recv_msg.body; - /* We're late! We're Late! */ + } else if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) { /* We're late! We're Late! */ + uint8_t *data = (uint8_t *) rtp_session->recv_msg.body; + if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK) && status == SWITCH_STATUS_BREAK) { switch_yield(1000); continue; @@ -942,7 +954,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ return 2 + rtp_header_len; } - + if (bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE)) { @@ -959,6 +971,9 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ bytes = sbytes; } + if (bytes > 0) { + rtp_session->missed_count = 0; + } if (status == SWITCH_STATUS_BREAK || bytes == 0) { if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_DATAWAIT)) {