- Timestamp:
- Feb 6, 2013 1:48:45 PM (12 years ago)
- Location:
- pjproject/trunk/pjsip
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r4288 r4342 2657 2657 pj_bool_t ice_no_rtcp; 2658 2658 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 2659 2669 } pjsua_ice_config; 2660 2670 … … 5552 5562 5553 5563 /** 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 /** 5554 5574 * Enable TURN relay candidate in ICE. 5555 5575 */ -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
r4300 r4342 156 156 157 157 struct { 158 pj_timer_entry reinv_timer;/**< Reinvite retry timer. */159 pj_uint32_t sdp_ver; /**< SDP version of the bad answer */160 158 int retry_cnt; /**< Retry count. */ 161 pj_bool_t pending; /**< Pending until CONFIRMED state */162 159 } lock_codec; /**< Data for codec locking when answer 163 160 contains multiple codecs. */ … … 186 183 unsigned rem_vid_cnt; /**< No of active video in last remote 187 184 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? */ 188 189 }; 189 190 … … 817 818 #endif 818 819 820 /* 821 * Schedule check for the need of re-INVITE/UPDATE after media update 822 */ 823 void pjsua_call_schedule_reinvite_check(pjsua_call *call, unsigned delay_ms); 819 824 820 825 PJ_END_DECL -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r4315 r4342 107 107 static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event); 108 108 109 /* Timer callback to send re-INVITE/UPDATE to lock codec or ICE update */ 110 static 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 */ 113 static pj_status_t process_pending_reinvite(pjsua_call *call); 114 109 115 /* 110 116 * Reset call descriptor. … … 129 135 } 130 136 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); 131 139 } 132 140 … … 2201 2209 } 2202 2210 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; 2208 2215 } 2209 2216 … … 2895 2902 2896 2903 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 */ 2905 static void reinv_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry) 2903 2906 { 2904 2907 pjsua_call_id call_id = (pjsua_call_id)(pj_size_t)entry->user_data; … … 2909 2912 PJ_UNUSED_ARG(th); 2910 2913 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(); 2912 2917 2913 2918 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(); 2915 2921 return; 2916 2917 status = perform_lock_codec(call); 2922 } 2923 2924 process_pending_reinvite(call); 2918 2925 2919 2926 pjsip_dlg_dec_lock(dlg); 2927 2928 pj_log_pop_indent(); 2920 2929 } 2921 2930 … … 2923 2932 /* Check if the specified format can be skipped in counting codecs */ 2924 2933 static pj_bool_t is_non_av_fmt(const pjmedia_sdp_media *m, 2925 2934 const pj_str_t *fmt) 2926 2935 { 2927 2936 const pj_str_t STR_TEL = {"telephone-event", 15}; … … 2956 2965 2957 2966 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 */ 2972 void 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 */ 2989 static 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; 2965 2993 unsigned i; 2966 pj_bool_t rem_can_update;2967 pj_bool_t need_lock_codec = PJ_FALSE;2968 pjsip_tx_data *tdata;2969 2994 pj_status_t status; 2970 2995 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. */ 2993 3009 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp); 2994 3010 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); 3135 3013 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) { 3143 3017 pjsua_call_media *call_med = &call->media[i]; 3144 3018 const pjmedia_sdp_media *rem_m, *loc_m; 3145 3019 unsigned codec_cnt = 0; 3020 unsigned j; 3146 3021 3147 3022 /* Skip this if the media is inactive or error */ … … 3164 3039 3165 3040 /* 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 */ 3055 static 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; 3173 3088 } 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 } 3178 3103 break; 3179 3104 } 3180 3105 } 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 */ 3114 static 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) 3185 3164 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. 3190 3201 */ 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 3208 3299 return PJ_SUCCESS; 3209 3300 } 3301 3210 3302 3211 3303 /* … … 3243 3335 pj_gettimeofday(&call->conn_time); 3244 3336 3245 /* See if lock codecwas pended as media update was done in the3337 /* See if auto reinvite was pended as media update was done in the 3246 3338 * EARLY state and remote does not support UPDATE. 3247 3339 */ 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); 3255 3343 } 3256 3344 break; … … 3274 3362 } 3275 3363 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; 3281 3368 } 3282 3369 break; … … 3561 3648 3562 3649 /* 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); 3567 3651 3568 3652 /* Call application callback, if any */ -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r4297 r4342 212 212 dst->ice_opt = src->ice_opt; 213 213 dst->ice_no_rtcp = src->ice_no_rtcp; 214 dst->ice_always_update = src->ice_always_update; 214 215 } 215 216 … … 325 326 326 327 cfg->ice_max_host_cands = -1; 328 cfg->ice_always_update = PJ_TRUE; 327 329 pj_ice_sess_options_default(&cfg->ice_opt); 328 330 -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r4336 r4342 586 586 } 587 587 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 than614 * 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 else650 pjsua_call_reinvite(call_med->call->index, 0, NULL);651 }652 653 if (dlg)654 pjsip_dlg_dec_lock(dlg);655 }656 657 588 658 589 /* This callback is called when ICE negotiation completes */ … … 662 593 { 663 594 pjsua_call_media *call_med = (pjsua_call_media*)tp->user_data; 595 pjsua_call *call; 664 596 665 597 if (!call_med) 666 598 return; 667 599 600 call = call_med->call; 601 668 602 switch (op) { 669 603 case PJ_ICE_STRANS_OP_INIT: … … 672 606 break; 673 607 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 { 675 615 call_med->state = PJSUA_CALL_MEDIA_ERROR; 676 616 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 } 685 620 } 621 /* Check if default ICE transport address is changed */ 622 call->reinv_ice_sent = PJ_FALSE; 623 pjsua_call_schedule_reinvite_check(call, 0); 686 624 break; 687 625 case PJ_ICE_STRANS_OP_KEEP_ALIVE: … … 689 627 PJ_PERROR(4,(THIS_FILE, result, 690 628 "ICE keep alive failure for transport %d:%d", 691 call _med->call->index, call_med->idx));629 call->index, call_med->idx)); 692 630 } 693 631 if (pjsua_var.ua_cfg.cb.on_call_media_transport_state) { … … 700 638 info.ext_info = &op; 701 639 (*pjsua_var.ua_cfg.cb.on_call_media_transport_state)( 702 call _med->call->index, &info);640 call->index, &info); 703 641 } 704 642 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; 706 644 (*pjsua_var.ua_cfg.cb.on_ice_transport_error)(id, op, result, 707 645 NULL); … … 856 794 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING, 857 795 pjsua_var.media_cfg.rx_drop_pct); 858 796 859 797 return PJ_SUCCESS; 860 798 … … 1340 1278 call_med->med_create_cb = &call_media_init_cb; 1341 1279 call_med->med_init_cb = cb; 1342 1280 1343 1281 return PJ_EPENDING; 1344 1282 }
Note: See TracChangeset
for help on using the changeset viewer.