Skip to content

Commit e5a6c68

Browse files
authored
Handle SSRC change after SRTP restart (#4490)
1 parent 55b117b commit e5a6c68

File tree

3 files changed

+68
-28
lines changed

3 files changed

+68
-28
lines changed

pjmedia/include/pjmedia/config.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,17 @@
12111211
#endif
12121212

12131213

1214+
/**
1215+
* Specify whether SRTP needs to handle condition that remote changes SSRC
1216+
* when SRTP is restarted.
1217+
*
1218+
* Default: enabled.
1219+
*/
1220+
#ifndef PJMEDIA_SRTP_CHECK_SSRC_ON_RESTART
1221+
# define PJMEDIA_SRTP_CHECK_SSRC_ON_RESTART 1
1222+
#endif
1223+
1224+
12141225
/**
12151226
* Specify whether SRTP needs to handle condition that old packets with
12161227
* incorect RTP seq are still coming when SRTP is restarted.

pjmedia/src/pjmedia/transport_srtp.c

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,7 @@ static pj_status_t create_srtp_ctx(transport_srtp *srtp,
986986
err = srtp_set_stream_roc(ctx->srtp_tx_ctx,
987987
setting->tx_roc.ssrc,
988988
setting->tx_roc.roc);
989-
PJ_LOG(4, (THIS_FILE, "Initializing SRTP TX ROC to SSRC %d with "
989+
PJ_LOG(4, (THIS_FILE, "Initializing SRTP TX ROC to SSRC %u with "
990990
"ROC %d %s\n", setting->tx_roc.ssrc,
991991
setting->tx_roc.roc,
992992
(err == srtp_err_status_ok)? "succeeded": "failed"));
@@ -1038,7 +1038,7 @@ static pj_status_t create_srtp_ctx(transport_srtp *srtp,
10381038
err = srtp_set_stream_roc(ctx->srtp_rx_ctx,
10391039
setting->rx_roc.ssrc,
10401040
setting->rx_roc.roc);
1041-
PJ_LOG(4, (THIS_FILE, "Initializing SRTP RX ROC from SSRC %d with "
1041+
PJ_LOG(4, (THIS_FILE, "Initializing SRTP RX ROC from SSRC %u with "
10421042
"ROC %d %s\n",
10431043
setting->rx_roc.ssrc, setting->rx_roc.roc,
10441044
(err == srtp_err_status_ok)? "succeeded": "failed"));
@@ -1399,7 +1399,7 @@ static pj_status_t transport_send_rtp( pjmedia_transport *tp,
13991399
if (status == srtp_err_status_ok) {
14001400
srtp->setting.tx_roc.ssrc = srtp->tx_ssrc;
14011401
srtp->setting.tx_roc.roc = (srtp->offerer_side? 1: 2);
1402-
PJ_LOG(4, (THIS_FILE, "Setting TX ROC to SSRC %d to %d",
1402+
PJ_LOG(4, (THIS_FILE, "Setting TX ROC to SSRC %u to %d",
14031403
srtp->tx_ssrc, srtp->setting.tx_roc.roc));
14041404
}
14051405
}
@@ -1549,6 +1549,8 @@ static void srtp_rtp_cb(pjmedia_tp_cb_param *param)
15491549
pj_ssize_t size = param->size;
15501550
int len = (int)size;
15511551
srtp_err_status_t err;
1552+
pj_bool_t need_restart = PJ_FALSE, need_retry = PJ_FALSE;
1553+
pj_uint32_t rx_ssrc;
15521554
void (*cb)(void*, void*, pj_ssize_t) = NULL;
15531555
void (*cb2)(pjmedia_tp_cb_param*) = NULL;
15541556
void *cb_data = NULL;
@@ -1624,7 +1626,7 @@ static void srtp_rtp_cb(pjmedia_tp_cb_param *param)
16241626
srtp->setting.rx_roc.ssrc = srtp->rx_ssrc;
16251627
srtp->setting.rx_roc.roc = (srtp->offerer_side? 2: 1);
16261628

1627-
PJ_LOG(4, (THIS_FILE, "Setting RX ROC from SSRC %d to %d",
1629+
PJ_LOG(4, (THIS_FILE, "Setting RX ROC from SSRC %u to %d",
16281630
srtp->rx_ssrc, srtp->setting.rx_roc.roc));
16291631
} else {
16301632
PJ_LOG(4, (THIS_FILE, "Setting RX ROC %s",
@@ -1635,22 +1637,59 @@ static void srtp_rtp_cb(pjmedia_tp_cb_param *param)
16351637

16361638
err = srtp_unprotect(srtp->srtp_ctx.srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
16371639

1640+
rx_ssrc = ntohl(((pjmedia_rtp_hdr*)pkt)->ssrc);
1641+
16381642
#if PJMEDIA_SRTP_CHECK_RTP_SEQ_ON_RESTART
1643+
/* Handle such condition that stream is updated (RTP seq is reinited
1644+
* & SRTP is restarted), but some old packets are still coming
1645+
* so SRTP is learning wrong RTP seq. While the newly inited RTP seq
1646+
* comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()
1647+
* will return err_status_replay_*. Restarting SRTP can resolve this.
1648+
*/
16391649
if (srtp->probation_cnt > 0 &&
16401650
(err == srtp_err_status_replay_old ||
16411651
err == srtp_err_status_replay_fail))
16421652
{
1643-
/* Handle such condition that stream is updated (RTP seq is reinited
1644-
* & SRTP is restarted), but some old packets are still coming
1645-
* so SRTP is learning wrong RTP seq. While the newly inited RTP seq
1646-
* comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()
1647-
* will return err_status_replay_*. Restarting SRTP can resolve this.
1653+
need_restart = PJ_TRUE;
1654+
PJ_LOG(5, (srtp->pool->obj_name, "Restarting SRTP err=%s",
1655+
get_libsrtp_errstr(err)));
1656+
}
1657+
#endif
1658+
1659+
#if PJMEDIA_SRTP_CHECK_SSRC_ON_RESTART
1660+
/* This could happen if remote changes ssrc, such as due to media
1661+
* restart.
1662+
*/
1663+
if (srtp->probation_cnt > 0 && err == srtp_err_status_no_ctx) {
1664+
need_restart = PJ_TRUE;
1665+
PJ_LOG(5, (srtp->pool->obj_name, "Restarting SRTP err=%s ssrc=%u",
1666+
get_libsrtp_errstr(err), rx_ssrc));
1667+
}
1668+
#endif
1669+
1670+
#if PJMEDIA_SRTP_CHECK_ROC_ON_RESTART
1671+
if (srtp->probation_cnt > 0 && err == srtp_err_status_auth_fail &&
1672+
srtp->setting.prev_rx_roc.ssrc != 0 &&
1673+
srtp->setting.prev_rx_roc.ssrc == srtp->setting.rx_roc.ssrc &&
1674+
srtp->setting.prev_rx_roc.roc != srtp->setting.rx_roc.roc)
1675+
{
1676+
need_retry = PJ_TRUE;
1677+
}
1678+
#endif
1679+
1680+
if (need_restart) {
1681+
/* Handle such condition that stream is updated and SRTP is restarted,
1682+
* but some old packets are still coming so SRTP is learning wrong SSRC
1683+
* or RTP seq. Restarting SRTP can resolve this.
16481684
*/
16491685
pjmedia_srtp_crypto tx, rx;
16501686
pj_status_t status;
16511687

16521688
tx = srtp->srtp_ctx.tx_policy;
16531689
rx = srtp->srtp_ctx.rx_policy;
1690+
/* If SRTP cannot find the context, reset the SSRC. */
1691+
if (err == srtp_err_status_no_ctx)
1692+
srtp->setting.rx_roc.ssrc = 0;
16541693

16551694
/* Stop SRTP first, otherwise srtp_start() will maintain current
16561695
* roll-over counter.
@@ -1660,24 +1699,15 @@ static void srtp_rtp_cb(pjmedia_tp_cb_param *param)
16601699
status = pjmedia_transport_srtp_start((pjmedia_transport*)srtp,
16611700
&tx, &rx);
16621701
if (status != PJ_SUCCESS) {
1663-
PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s",
1664-
get_libsrtp_errstr(err)));
1702+
PJ_PERROR(4, (srtp->pool->obj_name, status,
1703+
"Failed to restart SRTP, err=%s",
1704+
get_libsrtp_errstr(err)));
16651705
} else if (!srtp->bypass_srtp) {
16661706
err = srtp_unprotect(srtp->srtp_ctx.srtp_rx_ctx,
16671707
(pj_uint8_t*)pkt, &len);
16681708
}
1669-
}
1670-
#if PJMEDIA_SRTP_CHECK_ROC_ON_RESTART
1671-
else
1672-
#endif
1673-
#endif
16741709

1675-
#if PJMEDIA_SRTP_CHECK_ROC_ON_RESTART
1676-
if (srtp->probation_cnt > 0 && err == srtp_err_status_auth_fail &&
1677-
srtp->setting.prev_rx_roc.ssrc != 0 &&
1678-
srtp->setting.prev_rx_roc.ssrc == srtp->setting.rx_roc.ssrc &&
1679-
srtp->setting.prev_rx_roc.roc != srtp->setting.rx_roc.roc)
1680-
{
1710+
} else if (need_retry) {
16811711
unsigned roc, new_roc;
16821712
srtp_err_status_t status;
16831713

@@ -1695,19 +1725,18 @@ static void srtp_rtp_cb(pjmedia_tp_cb_param *param)
16951725
&len);
16961726
}
16971727
}
1698-
#endif
16991728

17001729
if (err != srtp_err_status_ok) {
17011730
PJ_LOG(5,(srtp->pool->obj_name,
1702-
"Failed to unprotect SRTP, pkt size=%ld, err=%s",
1703-
size, get_libsrtp_errstr(err)));
1731+
"Failed to unprotect SRTP, pkt size=%ld, SSRC=%u, err=%s",
1732+
size, rx_ssrc, get_libsrtp_errstr(err)));
17041733
} else {
17051734
cb = srtp->rtp_cb;
17061735
cb2 = srtp->rtp_cb2;
17071736
cb_data = srtp->user_data;
17081737

17091738
/* Save SSRC after successful SRTP unprotect */
1710-
srtp->rx_ssrc = ntohl(((pjmedia_rtp_hdr*)pkt)->ssrc);
1739+
srtp->rx_ssrc = rx_ssrc;
17111740
}
17121741

17131742
pj_lock_release(srtp->mutex);

pjsip/src/pjsua-lib/pjsua_media.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3711,10 +3711,10 @@ static void check_srtp_roc(pjsua_call *call,
37113711
}
37123712

37133713
#if 0
3714-
PJ_LOG(4, (THIS_FILE, "SRTP TX ROC %d %d",
3714+
PJ_LOG(4, (THIS_FILE, "SRTP TX ROC %u %d",
37153715
call_med->prev_srtp_info.tx_roc.ssrc,
37163716
call_med->prev_srtp_info.tx_roc.roc));
3717-
PJ_LOG(4, (THIS_FILE, "SRTP RX ROC %d %d",
3717+
PJ_LOG(4, (THIS_FILE, "SRTP RX ROC %u %d",
37183718
call_med->prev_srtp_info.rx_roc.ssrc,
37193719
call_med->prev_srtp_info.rx_roc.roc));
37203720
#endif

0 commit comments

Comments
 (0)