Ticket #600: ticket600.patch

File ticket600.patch, 3.2 KB (added by nanang, 13 years ago)

Added probation counter, inited when media_start() is called, when this counter > 0, SRTP may auto restart when unprotect() returns replay_fail

  • pjmedia/src/pjmedia/transport_srtp.c

     
    3636#define MAX_RTP_BUFFER_LEN          1500 
    3737#define MAX_RTCP_BUFFER_LEN         1500 
    3838#define MAX_KEY_LEN                 32 
     39 
     40/* Initial value of probation counter. When probation counter > 0,  
     41 * it means SRTP is in probation mode, and it may restart when 
     42 * srtp_unprotect() returns err_status_replay_* 
     43 */ 
     44#define PROBATION_CNT_INIT          100 
     45 
    3946#define DEACTIVATE_MEDIA(pool, m)   pjmedia_sdp_media_deactivate(pool, m) 
    4047 
    4148static const pj_str_t ID_RTP_AVP  = { "RTP/AVP", 7 }; 
     
    7683 
    7784typedef struct transport_srtp 
    7885{ 
    79     pjmedia_transport    base;      /**< Base transport interface. */ 
    80     pj_pool_t           *pool; 
    81     pj_lock_t           *mutex; 
     86    pjmedia_transport    base;              /**< Base transport interface. */ 
     87    pj_pool_t           *pool;              /**< Pool for transport SRTP.   */ 
     88    pj_lock_t           *mutex;             /**< Mutex for libsrtp contexts.*/ 
    8289    char                 rtp_tx_buffer[MAX_RTP_BUFFER_LEN]; 
    8390    char                 rtcp_tx_buffer[MAX_RTCP_BUFFER_LEN]; 
    8491    pjmedia_srtp_setting setting; 
     
    120127     */ 
    121128    pjmedia_srtp_use     peer_use; 
    122129 
     130    /* When probation counter > 0, it means SRTP is in probation mode,  
     131     * and it may restart when srtp_unprotect() returns err_status_replay_* 
     132     */ 
     133    unsigned             probation_cnt; 
    123134} transport_srtp; 
    124135 
    125136 
     
    349360    srtp->pool = pool; 
    350361    srtp->session_inited = PJ_FALSE; 
    351362    srtp->bypass_srtp = PJ_FALSE; 
     363    srtp->probation_cnt = PROBATION_CNT_INIT; 
    352364    srtp->peer_use = opt->use; 
    353365 
    354366    if (opt) { 
     
    775787    /* Make sure buffer is 32bit aligned */ 
    776788    PJ_ASSERT_ON_FAIL( (((long)pkt) & 0x03)==0, return ); 
    777789 
     790    if (srtp->probation_cnt > 0) 
     791        --srtp->probation_cnt; 
     792 
    778793    pj_lock_acquire(srtp->mutex); 
    779794 
    780795    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len); 
    781      
     796 
     797    if (srtp->probation_cnt > 0 &&  
     798        (err == err_status_replay_old || err == err_status_replay_fail))  
     799    { 
     800        /* Handle such condition that stream is updated (RTP seq is reinited 
     801        * & SRTP is restarted), but some old packets are still coming  
     802        * so SRTP is learning wrong RTP seq. While the newly inited RTP seq 
     803        * comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()  
     804        * will returning err_status_replay_*. Restarting SRTP can resolve  
     805        * this. 
     806        */ 
     807        if (pjmedia_transport_srtp_start((pjmedia_transport*)srtp,  
     808                                         &srtp->tx_policy, &srtp->rx_policy)  
     809                                         != PJ_SUCCESS) 
     810        { 
     811            PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s",  
     812                      get_libsrtp_errstr(err))); 
     813        } else { 
     814            err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len); 
     815        } 
     816    } 
     817 
    782818    if (err == err_status_ok) { 
    783819        srtp->rtp_cb(srtp->user_data, pkt, len); 
    784820    } else { 
     
    13781414        /* At this point, we get valid rx_policy_neg & tx_policy_neg. */ 
    13791415    } 
    13801416 
     1417    /* Reset probation counts */ 
     1418    srtp->probation_cnt = PROBATION_CNT_INIT; 
     1419 
    13811420    /* Got policy_local & policy_remote, let's initalize the SRTP */ 
    13821421    status = pjmedia_transport_srtp_start(tp, &srtp->tx_policy_neg, &srtp->rx_policy_neg); 
    13831422    if (status != PJ_SUCCESS)