Changeset 4342 for pjproject/trunk


Ignore:
Timestamp:
Feb 6, 2013 1:48:45 PM (12 years ago)
Author:
nanang
Message:

Close #1242: Single re-INVITE/UPDATE for both lock codec and ICE negotiation updates.

Location:
pjproject/trunk/pjsip
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r4288 r4342  
    26572657    pj_bool_t           ice_no_rtcp; 
    26582658 
     2659    /** 
     2660     * Send re-INVITE/UPDATE every after ICE connectivity check regardless 
     2661     * the default ICE transport address is changed or not. When this is set 
     2662     * to PJ_FALSE, re-INVITE/UPDATE will be sent only when the default ICE 
     2663     * transport address is changed. 
     2664     * 
     2665     * Default: yes 
     2666     */ 
     2667    pj_bool_t           ice_always_update; 
     2668 
    26592669} pjsua_ice_config; 
    26602670 
     
    55525562 
    55535563    /** 
     5564     * Send re-INVITE/UPDATE every after ICE connectivity check regardless 
     5565     * the default ICE transport address is changed or not. When this is set 
     5566     * to PJ_FALSE, re-INVITE/UPDATE will be sent only when the default ICE 
     5567     * transport address is changed. 
     5568     * 
     5569     * Default: yes 
     5570     */ 
     5571    pj_bool_t           ice_always_update; 
     5572 
     5573    /** 
    55545574     * Enable TURN relay candidate in ICE. 
    55555575     */ 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r4300 r4342  
    156156 
    157157    struct { 
    158         pj_timer_entry   reinv_timer;/**< Reinvite retry timer.             */ 
    159         pj_uint32_t      sdp_ver;    /**< SDP version of the bad answer     */ 
    160158        int              retry_cnt;  /**< Retry count.                      */ 
    161         pj_bool_t        pending;    /**< Pending until CONFIRMED state     */ 
    162159    } lock_codec;                    /**< Data for codec locking when answer 
    163160                                          contains multiple codecs.         */ 
     
    186183    unsigned             rem_vid_cnt;  /**< No of active video in last remote 
    187184                                            offer.                          */ 
     185     
     186    pj_timer_entry       reinv_timer;  /**< Reinvite retry timer.           */ 
     187    pj_bool_t            reinv_pending;/**< Pending until CONFIRMED state.  */ 
     188    pj_bool_t            reinv_ice_sent;/**< Has reinvite for ICE upd sent? */ 
    188189}; 
    189190 
     
    817818#endif 
    818819 
     820/* 
     821 * Schedule check for the need of re-INVITE/UPDATE after media update 
     822 */ 
     823void pjsua_call_schedule_reinvite_check(pjsua_call *call, unsigned delay_ms); 
    819824 
    820825PJ_END_DECL 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r4315 r4342  
    107107static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event); 
    108108 
     109/* Timer callback to send re-INVITE/UPDATE to lock codec or ICE update */ 
     110static void reinv_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry); 
     111 
     112/* Check and send reinvite for lock codec and ICE update */ 
     113static pj_status_t process_pending_reinvite(pjsua_call *call); 
     114 
    109115/* 
    110116 * Reset call descriptor. 
     
    129135    } 
    130136    pjsua_call_setting_default(&call->opt); 
     137    pj_timer_entry_init(&call->reinv_timer, PJ_FALSE, 
     138                        (void*)(pj_size_t)id, &reinv_timer_cb); 
    131139} 
    132140 
     
    22012209    } 
    22022210 
    2203     /* Stop lock codec timer, if it is active */ 
    2204     if (call->lock_codec.reinv_timer.id) { 
    2205         pjsip_endpt_cancel_timer(pjsua_var.endpt,  
    2206                                  &call->lock_codec.reinv_timer); 
    2207         call->lock_codec.reinv_timer.id = PJ_FALSE; 
     2211    /* Stop reinvite timer, if it is active */ 
     2212    if (call->reinv_timer.id) { 
     2213        pjsua_cancel_timer(&call->reinv_timer); 
     2214        call->reinv_timer.id = PJ_FALSE; 
    22082215    } 
    22092216 
     
    28952902 
    28962903 
    2897 /* Proto */ 
    2898 static pj_status_t perform_lock_codec(pjsua_call *call); 
    2899  
    2900 /* Timer callback to send re-INVITE or UPDATE to lock codec */ 
    2901 static void reinv_timer_cb(pj_timer_heap_t *th, 
    2902                            pj_timer_entry *entry) 
     2904/* Timer callback to send re-INVITE/UPDATE to lock codec or ICE update */ 
     2905static void reinv_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry) 
    29032906{ 
    29042907    pjsua_call_id call_id = (pjsua_call_id)(pj_size_t)entry->user_data; 
     
    29092912    PJ_UNUSED_ARG(th); 
    29102913 
    2911     pjsua_var.calls[call_id].lock_codec.reinv_timer.id = PJ_FALSE; 
     2914    pjsua_var.calls[call_id].reinv_timer.id = PJ_FALSE; 
     2915 
     2916    pj_log_push_indent(); 
    29122917 
    29132918    status = acquire_call("reinv_timer_cb()", call_id, &call, &dlg); 
    2914     if (status != PJ_SUCCESS) 
     2919    if (status != PJ_SUCCESS) { 
     2920        pj_log_pop_indent(); 
    29152921        return; 
    2916  
    2917     status = perform_lock_codec(call); 
     2922    } 
     2923 
     2924    process_pending_reinvite(call); 
    29182925 
    29192926    pjsip_dlg_dec_lock(dlg); 
     2927 
     2928    pj_log_pop_indent(); 
    29202929} 
    29212930 
     
    29232932/* Check if the specified format can be skipped in counting codecs */ 
    29242933static pj_bool_t is_non_av_fmt(const pjmedia_sdp_media *m, 
    2925                                   const pj_str_t *fmt) 
     2934                               const pj_str_t *fmt) 
    29262935{ 
    29272936    const pj_str_t STR_TEL = {"telephone-event", 15}; 
     
    29562965 
    29572966 
    2958 /* Send re-INVITE or UPDATE with new SDP offer to select only one codec 
    2959  * out of several codecs presented by callee in his answer. 
    2960  */ 
    2961 static pj_status_t perform_lock_codec(pjsua_call *call) 
    2962 { 
    2963     const pj_str_t STR_UPDATE = {"UPDATE", 6}; 
    2964     const pjmedia_sdp_session *local_sdp = NULL, *new_sdp; 
     2967/* Schedule check for the need of re-INVITE/UPDATE after media update, cases: 
     2968 * - lock codec if remote answerer has given us more than one codecs 
     2969 * - update ICE default transport address if it has changed after ICE 
     2970 *   connectivity check. 
     2971 */ 
     2972void pjsua_call_schedule_reinvite_check(pjsua_call *call, unsigned delay_ms) 
     2973{ 
     2974    pj_time_val delay; 
     2975 
     2976    /* Stop reinvite timer, if it is active */ 
     2977    if (call->reinv_timer.id) 
     2978        pjsua_cancel_timer(&call->reinv_timer); 
     2979 
     2980    delay.sec = 0; 
     2981    delay.msec = delay_ms; 
     2982    pj_time_val_normalize(&delay); 
     2983    call->reinv_timer.id = PJ_TRUE; 
     2984    pjsua_schedule_timer(&call->reinv_timer, &delay); 
     2985} 
     2986 
     2987 
     2988/* Check if lock codec is needed */ 
     2989static pj_bool_t check_lock_codec(pjsua_call *call) 
     2990{ 
     2991    const pjmedia_sdp_session *local_sdp, *remote_sdp; 
     2992    pj_bool_t has_mult_fmt = PJ_FALSE; 
    29652993    unsigned i; 
    2966     pj_bool_t rem_can_update; 
    2967     pj_bool_t need_lock_codec = PJ_FALSE; 
    2968     pjsip_tx_data *tdata; 
    29692994    pj_status_t status; 
    29702995 
    2971     PJ_ASSERT_RETURN(call->lock_codec.reinv_timer.id==PJ_FALSE, 
    2972                      PJ_EINVALIDOP); 
    2973  
    2974     /* Verify if another SDP negotiation is in progress, e.g: session timer 
    2975      * or another re-INVITE. 
    2976      */ 
    2977     if (call->inv==NULL || call->inv->neg==NULL || 
    2978         pjmedia_sdp_neg_get_state(call->inv->neg)!=PJMEDIA_SDP_NEG_STATE_DONE) 
    2979     { 
    2980         return PJMEDIA_SDPNEG_EINSTATE; 
    2981     } 
    2982  
    2983     /* Don't do this if call is disconnecting! */ 
    2984     if (call->inv->state > PJSIP_INV_STATE_CONFIRMED || 
    2985         call->inv->cause >= 200) 
    2986     { 
    2987         return PJ_EINVALIDOP; 
    2988     } 
    2989  
    2990     /* Verify if another SDP negotiation has been completed by comparing 
    2991      * the SDP version. 
    2992      */ 
     2996    /* Check if lock codec is disabled */ 
     2997    if (!pjsua_var.acc[call->acc_id].cfg.lock_codec) 
     2998        return PJ_FALSE; 
     2999 
     3000    /* Check lock codec retry count */ 
     3001    if (call->lock_codec.retry_cnt >= LOCK_CODEC_MAX_RETRY) 
     3002        return PJ_FALSE; 
     3003 
     3004    /* Check if we are the answerer, we shouldn't need to lock codec */ 
     3005    if (!call->inv->neg || !pjmedia_sdp_neg_was_answer_remote(call->inv->neg)) 
     3006        return PJ_FALSE; 
     3007 
     3008    /* Check if remote answerer has given us more than one codecs. */ 
    29933009    status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp); 
    29943010    if (status != PJ_SUCCESS) 
    2995         return status; 
    2996     if (local_sdp->origin.version > call->lock_codec.sdp_ver) 
    2997         return PJMEDIA_SDP_EINVER; 
    2998  
    2999     PJ_LOG(3, (THIS_FILE, "Updating media session to use only one codec..")); 
    3000  
    3001     /* Update the new offer so it contains only a codec. Note that formats 
    3002      * order in the offer should have been matched to the answer, so we can 
    3003      * just directly update the offer without looking-up the answer. 
    3004      */ 
    3005     new_sdp = pjmedia_sdp_session_clone(call->inv->pool_prov, local_sdp); 
    3006  
    3007     for (i = 0; i < call->med_cnt; ++i) { 
    3008         unsigned j = 0, codec_cnt = 0; 
    3009         const pjmedia_sdp_media *ref_m; 
    3010         pjmedia_sdp_media *m; 
    3011         pjsua_call_media *call_med = &call->media[i]; 
    3012  
    3013         /* Verify if media is deactivated */ 
    3014         if (call_med->state == PJSUA_CALL_MEDIA_NONE || 
    3015             call_med->state == PJSUA_CALL_MEDIA_ERROR || 
    3016             call_med->dir == PJMEDIA_DIR_NONE) 
    3017         { 
    3018             continue; 
    3019         } 
    3020  
    3021         ref_m = local_sdp->media[i]; 
    3022         m = new_sdp->media[i]; 
    3023  
    3024         /* Verify that media must be active. */ 
    3025         pj_assert(ref_m->desc.port); 
    3026  
    3027         while (j < m->desc.fmt_count) { 
    3028             pjmedia_sdp_attr *a; 
    3029             pj_str_t *fmt = &m->desc.fmt[j]; 
    3030  
    3031             if (is_non_av_fmt(m, fmt) || (++codec_cnt == 1)) { 
    3032                 ++j; 
    3033                 continue; 
    3034             } 
    3035  
    3036             /* Remove format */ 
    3037             a = pjmedia_sdp_attr_find2(m->attr_count, m->attr, "rtpmap", fmt); 
    3038             if (a) pjmedia_sdp_attr_remove(&m->attr_count, m->attr, a); 
    3039             a = pjmedia_sdp_attr_find2(m->attr_count, m->attr, "fmtp", fmt); 
    3040             if (a) pjmedia_sdp_attr_remove(&m->attr_count, m->attr, a); 
    3041             pj_array_erase(m->desc.fmt, sizeof(m->desc.fmt[0]), 
    3042                            m->desc.fmt_count, j); 
    3043             --m->desc.fmt_count; 
    3044         } 
    3045          
    3046         need_lock_codec |= (ref_m->desc.fmt_count > m->desc.fmt_count); 
    3047     } 
    3048  
    3049     /* Last check if SDP trully needs to be updated. It is possible that OA 
    3050      * negotiations have completed and SDP has changed but we didn't 
    3051      * increase the SDP version (should not happen!). 
    3052      */ 
    3053     if (!need_lock_codec) 
    3054         return PJ_SUCCESS; 
    3055  
    3056     /* Send UPDATE or re-INVITE */ 
    3057     rem_can_update = pjsip_dlg_remote_has_cap(call->inv->dlg, 
    3058                                               PJSIP_H_ALLOW, 
    3059                                               NULL, &STR_UPDATE) == 
    3060                                                 PJSIP_DIALOG_CAP_SUPPORTED; 
    3061     if (rem_can_update) { 
    3062         status = pjsip_inv_update(call->inv, NULL, new_sdp, &tdata); 
    3063     } else { 
    3064         status = pjsip_inv_reinvite(call->inv, NULL, new_sdp, &tdata); 
    3065     } 
    3066  
    3067     if (status==PJ_EINVALIDOP && 
    3068         ++call->lock_codec.retry_cnt <= LOCK_CODEC_MAX_RETRY) 
    3069     { 
    3070         /* Ups, let's reschedule again */ 
    3071         pj_time_val delay = {0, LOCK_CODEC_RETRY_INTERVAL}; 
    3072         pj_time_val_normalize(&delay); 
    3073         call->lock_codec.reinv_timer.id = PJ_TRUE; 
    3074         pjsip_endpt_schedule_timer(pjsua_var.endpt, 
    3075                                    &call->lock_codec.reinv_timer, &delay); 
    3076         return status; 
    3077     } else if (status != PJ_SUCCESS) { 
    3078         pjsua_perror(THIS_FILE, "Error creating UPDATE/re-INVITE to lock codec", 
    3079                      status); 
    3080         return status; 
    3081     } 
    3082  
    3083     /* Send the UPDATE/re-INVITE request */ 
    3084     status = pjsip_inv_send_msg(call->inv, tdata); 
    3085     if (status != PJ_SUCCESS) { 
    3086         pjsua_perror(THIS_FILE, "Error sending UPDATE/re-INVITE in lock codec", 
    3087                      status); 
    3088         return status; 
    3089     } 
    3090  
    3091     return status; 
    3092 } 
    3093  
    3094 /* Check if remote answerer has given us more than one codecs. If so, 
    3095  * create another offer with one codec only to lock down the codec. 
    3096  */ 
    3097 static pj_status_t lock_codec(pjsua_call *call) 
    3098 { 
    3099     pjsip_inv_session *inv = call->inv; 
    3100     const pjmedia_sdp_session *local_sdp, *remote_sdp; 
    3101     pj_time_val delay = {0, 0}; 
    3102     const pj_str_t st_update = {"UPDATE", 6}; 
    3103     unsigned i; 
    3104     pj_bool_t has_mult_fmt = PJ_FALSE; 
    3105     pj_status_t status; 
    3106  
    3107     if (!pjsua_var.acc[call->acc_id].cfg.lock_codec) { 
    3108         return PJ_SUCCESS; 
    3109     } 
    3110  
    3111     /* Stop lock codec timer, if it is active */ 
    3112     if (call->lock_codec.reinv_timer.id) { 
    3113         pjsip_endpt_cancel_timer(pjsua_var.endpt, 
    3114                                  &call->lock_codec.reinv_timer); 
    3115         call->lock_codec.reinv_timer.id = PJ_FALSE; 
    3116     } 
    3117  
    3118     /* Skip this if we are the answerer */ 
    3119     if (!inv->neg || !pjmedia_sdp_neg_was_answer_remote(inv->neg)) { 
    3120         return PJ_SUCCESS; 
    3121     } 
    3122  
    3123     /* Delay this when the SDP negotiation done in call state EARLY and 
    3124      * remote does not support UPDATE method. 
    3125      */ 
    3126     if (inv->state == PJSIP_INV_STATE_EARLY &&  
    3127         pjsip_dlg_remote_has_cap(inv->dlg, PJSIP_H_ALLOW, NULL, &st_update)!= 
    3128         PJSIP_DIALOG_CAP_SUPPORTED) 
    3129     { 
    3130         call->lock_codec.pending = PJ_TRUE; 
    3131         return PJ_SUCCESS; 
    3132     } 
    3133  
    3134     status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp); 
     3011        return PJ_FALSE; 
     3012    status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp); 
    31353013    if (status != PJ_SUCCESS) 
    3136         return status; 
    3137     status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp); 
    3138     if (status != PJ_SUCCESS) 
    3139         return status; 
    3140  
    3141     /* Find multiple codecs answer in all media */ 
    3142     for (i = 0; i < call->med_cnt; ++i) { 
     3014        return PJ_FALSE; 
     3015 
     3016    for (i = 0; i < call->med_cnt && !has_mult_fmt; ++i) { 
    31433017        pjsua_call_media *call_med = &call->media[i]; 
    31443018        const pjmedia_sdp_media *rem_m, *loc_m; 
    31453019        unsigned codec_cnt = 0; 
     3020        unsigned j; 
    31463021 
    31473022        /* Skip this if the media is inactive or error */ 
     
    31643039 
    31653040        /* Count the formats in the answer. */ 
    3166         if (rem_m->desc.fmt_count==1) { 
    3167             codec_cnt = 1; 
    3168         } else { 
    3169             unsigned j; 
    3170             for (j=0; j<rem_m->desc.fmt_count && codec_cnt <= 1; ++j) { 
    3171                 if (!is_non_av_fmt(rem_m, &rem_m->desc.fmt[j])) 
    3172                     ++codec_cnt; 
     3041        for (j=0; j<rem_m->desc.fmt_count && codec_cnt <= 1; ++j) { 
     3042            if (!is_non_av_fmt(rem_m, &rem_m->desc.fmt[j]) && ++codec_cnt > 1) 
     3043                has_mult_fmt = PJ_TRUE; 
     3044        } 
     3045    } 
     3046 
     3047    /* Reset retry count when remote answer has one codec */ 
     3048    if (!has_mult_fmt) 
     3049        call->lock_codec.retry_cnt = 0; 
     3050 
     3051    return has_mult_fmt; 
     3052} 
     3053 
     3054/* Check if ICE setup is complete and if it needs to send reinvite */ 
     3055static pj_bool_t check_ice_complete(pjsua_call *call, pj_bool_t *need_reinv) 
     3056{ 
     3057    pj_bool_t ice_need_reinv = PJ_FALSE; 
     3058    pj_bool_t ice_complete = PJ_TRUE; 
     3059    unsigned i; 
     3060 
     3061    /* Check if ICE setup is complete and if it needs reinvite */ 
     3062    for (i = 0; i < call->med_cnt && ice_complete; ++i) { 
     3063        pjsua_call_media *call_med = &call->media[i]; 
     3064        pjmedia_transport_info tpinfo; 
     3065        unsigned j; 
     3066         
     3067        if (call_med->tp_st == PJSUA_MED_TP_NULL || 
     3068            call_med->tp_st == PJSUA_MED_TP_DISABLED || 
     3069            call_med->state == PJSUA_CALL_MEDIA_ERROR) 
     3070        { 
     3071            continue; 
     3072        } 
     3073         
     3074        pjmedia_transport_info_init(&tpinfo); 
     3075        pjmedia_transport_get_info(call_med->tp, &tpinfo); 
     3076        for (j = 0; j < tpinfo.specific_info_cnt; ++j) { 
     3077            pjmedia_ice_transport_info *ice_info; 
     3078             
     3079            if (tpinfo.spc_info[j].type != PJMEDIA_TRANSPORT_TYPE_ICE) 
     3080                continue; 
     3081             
     3082            ice_info = (pjmedia_ice_transport_info*)tpinfo.spc_info[j].buffer; 
     3083             
     3084            /* Check if ICE setup not completed yet */ 
     3085            if (ice_info->sess_state < PJ_ICE_STRANS_STATE_RUNNING) { 
     3086                ice_complete = PJ_FALSE; 
     3087                break; 
    31733088            } 
    3174         } 
    3175  
    3176         if (codec_cnt > 1) { 
    3177             has_mult_fmt = PJ_TRUE; 
     3089             
     3090            /* Check if ICE needs to send reinvite */ 
     3091            if (!ice_need_reinv && 
     3092                ice_info->sess_state == PJ_ICE_STRANS_STATE_RUNNING && 
     3093                ice_info->role == PJ_ICE_SESS_ROLE_CONTROLLING) 
     3094            { 
     3095                pjsua_ice_config *cfg=&pjsua_var.acc[call->acc_id].cfg.ice_cfg; 
     3096                if ((cfg->ice_always_update && !call->reinv_ice_sent) || 
     3097                    pj_sockaddr_cmp(&tpinfo.sock_info.rtp_addr_name, 
     3098                                    &call_med->rtp_addr)) 
     3099                { 
     3100                    ice_need_reinv = PJ_TRUE; 
     3101                } 
     3102            } 
    31783103            break; 
    31793104        } 
    31803105    } 
    3181  
    3182     /* Each media in the answer already contains single codec. */ 
    3183     if (!has_mult_fmt) { 
    3184         call->lock_codec.retry_cnt = 0; 
     3106     
     3107    if (ice_complete && need_reinv) 
     3108        *need_reinv = ice_need_reinv; 
     3109     
     3110    return ice_complete; 
     3111} 
     3112 
     3113/* Check and send reinvite for lock codec and ICE update */ 
     3114static pj_status_t process_pending_reinvite(pjsua_call *call) 
     3115{ 
     3116    const pj_str_t ST_UPDATE = {"UPDATE", 6}; 
     3117    pj_pool_t *pool = call->inv->pool_prov; 
     3118    pjsip_inv_session *inv = call->inv; 
     3119    pj_bool_t ice_need_reinv; 
     3120    pj_bool_t ice_completed; 
     3121    pj_bool_t need_lock_codec; 
     3122    pj_bool_t rem_can_update; 
     3123    pjmedia_sdp_session *new_offer; 
     3124    pjsip_tx_data *tdata; 
     3125    unsigned i; 
     3126    pj_status_t status; 
     3127 
     3128    /* Verify if another SDP negotiation is in progress, e.g: session timer 
     3129     * or another re-INVITE. 
     3130     */ 
     3131    if (inv==NULL || inv->neg==NULL || 
     3132        pjmedia_sdp_neg_get_state(inv->neg)!=PJMEDIA_SDP_NEG_STATE_DONE) 
     3133    { 
     3134        return PJMEDIA_SDPNEG_EINSTATE; 
     3135    } 
     3136 
     3137    /* Don't do this if call is disconnecting! */ 
     3138    if (inv->state > PJSIP_INV_STATE_CONFIRMED || inv->cause >= 200) 
     3139    { 
     3140        return PJ_EINVALIDOP; 
     3141    } 
     3142 
     3143    /* Delay this when the SDP negotiation done in call state EARLY and 
     3144     * remote does not support UPDATE method. 
     3145     */ 
     3146    if (inv->state == PJSIP_INV_STATE_EARLY &&  
     3147        pjsip_dlg_remote_has_cap(inv->dlg, PJSIP_H_ALLOW, NULL, &ST_UPDATE)!= 
     3148        PJSIP_DIALOG_CAP_SUPPORTED) 
     3149    { 
     3150        call->reinv_pending = PJ_TRUE; 
     3151        return PJ_EPENDING; 
     3152    } 
     3153 
     3154    /* Check if ICE setup is complete and if it needs reinvite */ 
     3155    ice_completed = check_ice_complete(call, &ice_need_reinv); 
     3156    if (!ice_completed) 
     3157        return PJ_EPENDING; 
     3158 
     3159    /* Check if we need to lock codec */ 
     3160    need_lock_codec = check_lock_codec(call); 
     3161 
     3162    /* Check if reinvite is really needed */ 
     3163    if (!need_lock_codec && !ice_need_reinv) 
    31853164        return PJ_SUCCESS; 
    3186     } 
    3187  
    3188     /* Remote keeps answering with multiple codecs, let's just give up 
    3189      * locking codec to avoid infinite retry loop. 
     3165 
     3166     
     3167    /* Okay! So we need to send re-INVITE/UPDATE */ 
     3168 
     3169    /* Check if remote support UPDATE */ 
     3170    rem_can_update = pjsip_dlg_remote_has_cap(inv->dlg, PJSIP_H_ALLOW, NULL, 
     3171                                              &ST_UPDATE) == 
     3172                                                PJSIP_DIALOG_CAP_SUPPORTED; 
     3173 
     3174    /* Logging stuff */ 
     3175    { 
     3176        const char *ST_ICE_UPDATE = "ICE transport address after " 
     3177                                    "ICE negotiation"; 
     3178        const char *ST_LOCK_CODEC = "media session to use only one codec"; 
     3179        PJ_LOG(4,(THIS_FILE, "Call %d sending %s for updating %s%s%s", 
     3180                  call->index, 
     3181                  (rem_can_update? "UPDATE" : "re-INVITE"), 
     3182                  (ice_need_reinv? ST_ICE_UPDATE : ST_LOCK_CODEC), 
     3183                  (ice_need_reinv && need_lock_codec? " and " : ""), 
     3184                  (ice_need_reinv && need_lock_codec? ST_LOCK_CODEC : "") 
     3185                  )); 
     3186    } 
     3187     
     3188    /* Generate SDP re-offer */ 
     3189    status = pjsua_media_channel_create_sdp(call->index, pool, NULL, 
     3190                                            &new_offer, NULL); 
     3191    if (status != PJ_SUCCESS) { 
     3192        pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
     3193        return status; 
     3194    } 
     3195 
     3196    /* Update the new offer so it contains only a codec. Note that 
     3197     * SDP nego has removed unmatched codecs from the offer and the codec 
     3198     * order in the offer has been matched to the answer, so we'll override 
     3199     * the codecs in the just generated SDP with the ones from the active 
     3200     * local SDP and leave just one codec for the next SDP re-offer. 
    31903201     */ 
    3191     if (++call->lock_codec.retry_cnt > LOCK_CODEC_MAX_RETRY) 
    3192         return PJ_SUCCESS; 
    3193  
    3194     PJ_LOG(4, (THIS_FILE, "Got answer with multiple codecs, scheduling " 
    3195                           "updating media session to use only one codec..")); 
    3196  
    3197     call->lock_codec.sdp_ver = local_sdp->origin.version; 
    3198  
    3199     /* Can't send UPDATE or re-INVITE now, so just schedule it immediately. 
    3200      * See: https://trac.pjsip.org/repos/ticket/1149 
    3201      */ 
    3202     pj_timer_entry_init(&call->lock_codec.reinv_timer, PJ_TRUE, 
    3203                         (void*)(pj_size_t)call->index, 
    3204                         &reinv_timer_cb); 
    3205     pjsip_endpt_schedule_timer(pjsua_var.endpt, 
    3206                                &call->lock_codec.reinv_timer, &delay); 
    3207  
     3202    if (need_lock_codec) { 
     3203        const pjmedia_sdp_session *ref_sdp; 
     3204         
     3205        /* Get local active SDP as reference */ 
     3206        status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &ref_sdp); 
     3207        if (status != PJ_SUCCESS) 
     3208            return status; 
     3209         
     3210        /* Verify media count. Note that remote may add/remove media line 
     3211         * in the answer. When answer has less media, it must have been 
     3212         * handled by pjsua_media_channel_update() as disabled media. 
     3213         * When answer has more media, it must have been ignored (treated 
     3214         * as non-exist) anywhere. Local media count should not be updated 
     3215         * at this point, as modifying media count operation (i.e: reinvite, 
     3216         * update, vid_set_strm) is currently blocking, protected with 
     3217         * dialog mutex, and eventually reset SDP nego state to LOCAL OFFER. 
     3218         */ 
     3219        if (call->med_cnt != ref_sdp->media_count || 
     3220            ref_sdp->media_count != new_offer->media_count) 
     3221        { 
     3222            /* Anyway, just in case, let's just return error */ 
     3223            return PJMEDIA_SDPNEG_EINSTATE; 
     3224        } 
     3225 
     3226        for (i = 0; i < call->med_cnt; ++i) { 
     3227            unsigned j, codec_cnt = 0; 
     3228            const pjmedia_sdp_media *ref_m = ref_sdp->media[i]; 
     3229            pjmedia_sdp_media *m = new_offer->media[i]; 
     3230            pjsua_call_media *call_med = &call->media[i]; 
     3231     
     3232            /* Verify if media is deactivated */ 
     3233            if (call_med->state == PJSUA_CALL_MEDIA_NONE || 
     3234                call_med->state == PJSUA_CALL_MEDIA_ERROR || 
     3235                call_med->dir == PJMEDIA_DIR_NONE) 
     3236            { 
     3237                continue; 
     3238            } 
     3239     
     3240            /* Reset formats */ 
     3241            m->desc.fmt_count = 0; 
     3242            pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, "rtpmap"); 
     3243            pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, "fmtp"); 
     3244             
     3245            /* Copy only the first format + any non-AV formats from 
     3246             * the active local SDP. 
     3247             */ 
     3248            for (j = 0; j < ref_m->desc.fmt_count; ++j) { 
     3249                const pj_str_t *fmt = &ref_m->desc.fmt[j]; 
     3250 
     3251                if (is_non_av_fmt(ref_m, fmt) || (++codec_cnt == 1)) { 
     3252                    pjmedia_sdp_attr *a; 
     3253                     
     3254                    m->desc.fmt[m->desc.fmt_count++] = *fmt; 
     3255                    a = pjmedia_sdp_attr_find2(ref_m->attr_count, ref_m->attr, 
     3256                                               "rtpmap", fmt); 
     3257                    if (a) pjmedia_sdp_attr_add(&m->attr_count, m->attr, a); 
     3258                    a = pjmedia_sdp_attr_find2(ref_m->attr_count, ref_m->attr, 
     3259                                               "fmtp", fmt); 
     3260                    if (a) pjmedia_sdp_attr_add(&m->attr_count, m->attr, a); 
     3261                } 
     3262     
     3263            } 
     3264        } 
     3265    } 
     3266     
     3267    if (rem_can_update) { 
     3268        status = pjsip_inv_update(inv, NULL, new_offer, &tdata); 
     3269    } else { 
     3270        status = pjsip_inv_reinvite(inv, NULL, new_offer, &tdata); 
     3271    } 
     3272 
     3273    if (status==PJ_EINVALIDOP && 
     3274        ++call->lock_codec.retry_cnt < LOCK_CODEC_MAX_RETRY) 
     3275    { 
     3276        /* Ups, let's reschedule again */ 
     3277        pjsua_call_schedule_reinvite_check(call, LOCK_CODEC_RETRY_INTERVAL); 
     3278        return PJ_SUCCESS; 
     3279    } else if (status != PJ_SUCCESS) { 
     3280        pjsua_perror(THIS_FILE, "Error creating UPDATE/re-INVITE", 
     3281                     status); 
     3282        return status; 
     3283    } 
     3284 
     3285    /* Send the UPDATE/re-INVITE request */ 
     3286    status = pjsip_inv_send_msg(inv, tdata); 
     3287    if (status != PJ_SUCCESS) { 
     3288        pjsua_perror(THIS_FILE, "Error sending UPDATE/re-INVITE", 
     3289                     status); 
     3290        return status; 
     3291    } 
     3292 
     3293    /* Update flags */ 
     3294    if (ice_need_reinv) 
     3295        call->reinv_ice_sent = PJ_TRUE; 
     3296    if (need_lock_codec) 
     3297        ++call->lock_codec.retry_cnt; 
     3298     
    32083299    return PJ_SUCCESS; 
    32093300} 
     3301 
    32103302 
    32113303/* 
     
    32433335            pj_gettimeofday(&call->conn_time); 
    32443336 
    3245             /* See if lock codec was pended as media update was done in the 
     3337            /* See if auto reinvite was pended as media update was done in the 
    32463338             * EARLY state and remote does not support UPDATE. 
    32473339             */ 
    3248             if (call->lock_codec.pending) { 
    3249                 pj_status_t status; 
    3250                 status = lock_codec(call); 
    3251                 if (status != PJ_SUCCESS) { 
    3252                     pjsua_perror(THIS_FILE, "Unable to lock codec", status); 
    3253                 } 
    3254                 call->lock_codec.pending = PJ_FALSE; 
     3340            if (call->reinv_pending) { 
     3341                call->reinv_pending = PJ_FALSE; 
     3342                pjsua_call_schedule_reinvite_check(call, 0); 
    32553343            } 
    32563344            break; 
     
    32743362            } 
    32753363 
    3276             /* Stop lock codec timer, if it is active */ 
    3277             if (call->lock_codec.reinv_timer.id) { 
    3278                 pjsip_endpt_cancel_timer(pjsua_var.endpt,  
    3279                                          &call->lock_codec.reinv_timer); 
    3280                 call->lock_codec.reinv_timer.id = PJ_FALSE; 
     3364            /* Stop reinvite timer, if it is active */ 
     3365            if (call->reinv_timer.id) { 
     3366                pjsua_cancel_timer(&call->reinv_timer); 
     3367                call->reinv_timer.id = PJ_FALSE; 
    32813368            } 
    32823369            break; 
     
    35613648 
    35623649    /* Ticket #476: make sure only one codec is specified in the answer. */ 
    3563     status = lock_codec(call); 
    3564     if (status != PJ_SUCCESS) { 
    3565         pjsua_perror(THIS_FILE, "Unable to lock codec", status); 
    3566     } 
     3650    pjsua_call_schedule_reinvite_check(call, 0); 
    35673651 
    35683652    /* Call application callback, if any */ 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r4297 r4342  
    212212    dst->ice_opt = src->ice_opt; 
    213213    dst->ice_no_rtcp = src->ice_no_rtcp; 
     214    dst->ice_always_update = src->ice_always_update; 
    214215} 
    215216 
     
    325326 
    326327    cfg->ice_max_host_cands = -1; 
     328    cfg->ice_always_update = PJ_TRUE; 
    327329    pj_ice_sess_options_default(&cfg->ice_opt); 
    328330 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r4336 r4342  
    586586} 
    587587 
    588 static void med_tp_nego_timer_cb(void *user_data) 
    589 { 
    590     pjsua_call *call; 
    591     unsigned med_idx = (unsigned)(((long)user_data) & 0xFFFF); 
    592     pjsua_call_media *call_med; 
    593     pjmedia_transport *tp; 
    594     pjmedia_transport_info tpinfo; 
    595     pjmedia_ice_transport_info *ii = NULL; 
    596     unsigned i; 
    597     pjsip_dialog *dlg = NULL; 
    598  
    599     if ((acquire_call("med_tp_nego_timer_cb", ((long)user_data) >> 16, 
    600                      &call, &dlg) != PJ_SUCCESS) || 
    601         (med_idx >= call->med_cnt)) 
    602     { 
    603         /* Call have been terminated or media has been removed */ 
    604         return; 
    605     } 
    606  
    607     call_med = &call->media[med_idx]; 
    608     tp = call_med->tp; 
    609  
    610     if (!tp) 
    611         return; 
    612  
    613     /* Send UPDATE if default transport address is different than 
    614      * what was advertised (ticket #881) 
    615      */ 
    616  
    617     pjmedia_transport_info_init(&tpinfo); 
    618     pjmedia_transport_get_info(tp, &tpinfo); 
    619     for (i=0; i<tpinfo.specific_info_cnt; ++i) { 
    620         if (tpinfo.spc_info[i].type==PJMEDIA_TRANSPORT_TYPE_ICE) { 
    621             ii = (pjmedia_ice_transport_info*) 
    622             tpinfo.spc_info[i].buffer; 
    623             break; 
    624         } 
    625     } 
    626  
    627     if (ii && ii->role==PJ_ICE_SESS_ROLE_CONTROLLING && 
    628         pj_sockaddr_cmp(&tpinfo.sock_info.rtp_addr_name, 
    629                         &call_med->rtp_addr)) 
    630     { 
    631         pj_bool_t use_update; 
    632         const pj_str_t STR_UPDATE = { "UPDATE", 6 }; 
    633         pjsip_dialog_cap_status support_update; 
    634         pjsip_dialog *dlg; 
    635  
    636         dlg = call_med->call->inv->dlg; 
    637         support_update = pjsip_dlg_remote_has_cap(dlg, PJSIP_H_ALLOW, 
    638                                                   NULL, &STR_UPDATE); 
    639         use_update = (support_update == PJSIP_DIALOG_CAP_SUPPORTED); 
    640  
    641         PJ_LOG(4,(THIS_FILE,  
    642                   "ICE default transport address has changed for " 
    643                   "call %d, sending %s", 
    644                   call_med->call->index, 
    645                   (use_update ? "UPDATE" : "re-INVITE"))); 
    646  
    647         if (use_update) 
    648             pjsua_call_update(call_med->call->index, 0, NULL); 
    649         else 
    650             pjsua_call_reinvite(call_med->call->index, 0, NULL); 
    651     } 
    652  
    653     if (dlg) 
    654         pjsip_dlg_dec_lock(dlg); 
    655 } 
    656  
    657588 
    658589/* This callback is called when ICE negotiation completes */ 
     
    662593{ 
    663594    pjsua_call_media *call_med = (pjsua_call_media*)tp->user_data; 
     595    pjsua_call *call; 
    664596 
    665597    if (!call_med) 
    666598        return; 
    667599 
     600    call = call_med->call; 
     601     
    668602    switch (op) { 
    669603    case PJ_ICE_STRANS_OP_INIT: 
     
    672606        break; 
    673607    case PJ_ICE_STRANS_OP_NEGOTIATION: 
    674         if (result != PJ_SUCCESS) { 
     608        if (result == PJ_SUCCESS) { 
     609            /* Update RTP address */ 
     610            pjmedia_transport_info tpinfo; 
     611            pjmedia_transport_info_init(&tpinfo); 
     612            pjmedia_transport_get_info(call_med->tp, &tpinfo); 
     613            pj_sockaddr_cp(&call_med->rtp_addr, &tpinfo.sock_info.rtp_addr_name); 
     614        } else { 
    675615            call_med->state = PJSUA_CALL_MEDIA_ERROR; 
    676616            call_med->dir = PJMEDIA_DIR_NONE; 
    677  
    678             if (call_med->call && pjsua_var.ua_cfg.cb.on_call_media_state) { 
    679                 pjsua_var.ua_cfg.cb.on_call_media_state(call_med->call->index); 
    680             } 
    681         } else if (call_med->call) { 
    682             void *data = (void*)(long)( (call_med->call->index<<16) | 
    683                                         (call_med->idx & 0xFFFF) ); 
    684             pjsua_schedule_timer2(&med_tp_nego_timer_cb, data, 1); 
     617            if (call && pjsua_var.ua_cfg.cb.on_call_media_state) { 
     618                pjsua_var.ua_cfg.cb.on_call_media_state(call->index); 
     619            } 
    685620        } 
     621        /* Check if default ICE transport address is changed */ 
     622        call->reinv_ice_sent = PJ_FALSE; 
     623        pjsua_call_schedule_reinvite_check(call, 0); 
    686624        break; 
    687625    case PJ_ICE_STRANS_OP_KEEP_ALIVE: 
     
    689627            PJ_PERROR(4,(THIS_FILE, result, 
    690628                         "ICE keep alive failure for transport %d:%d", 
    691                          call_med->call->index, call_med->idx)); 
     629                         call->index, call_med->idx)); 
    692630        } 
    693631        if (pjsua_var.ua_cfg.cb.on_call_media_transport_state) { 
     
    700638            info.ext_info = &op; 
    701639            (*pjsua_var.ua_cfg.cb.on_call_media_transport_state)( 
    702                 call_med->call->index, &info); 
     640                call->index, &info); 
    703641        } 
    704642        if (pjsua_var.ua_cfg.cb.on_ice_transport_error) { 
    705             pjsua_call_id id = call_med->call->index; 
     643            pjsua_call_id id = call->index; 
    706644            (*pjsua_var.ua_cfg.cb.on_ice_transport_error)(id, op, result, 
    707645                                                          NULL); 
     
    856794    pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING, 
    857795                                    pjsua_var.media_cfg.rx_drop_pct); 
    858  
     796     
    859797    return PJ_SUCCESS; 
    860798 
     
    13401278                call_med->med_create_cb = &call_media_init_cb; 
    13411279                call_med->med_init_cb = cb; 
    1342  
     1280                 
    13431281                return PJ_EPENDING; 
    13441282            } 
Note: See TracChangeset for help on using the changeset viewer.