From eb531db72bd93280e47a6a03782da093eb8b2505 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 27 Mar 2007 11:01:45 +0000 Subject: Fixed ticket #203: Fix error when telephone-event is set as the first format in SDP (thanks Chris Hamilton) git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1109 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/src/pjmedia/session.c | 39 +++++++++++++++++++++++++++++++-------- pjsip/src/pjsua-lib/pjsua_call.c | 11 +++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/pjmedia/src/pjmedia/session.c b/pjmedia/src/pjmedia/session.c index 4dcc6a74..6e29e257 100644 --- a/pjmedia/src/pjmedia/session.c +++ b/pjmedia/src/pjmedia/session.c @@ -125,7 +125,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( const pjmedia_sdp_conn *rem_conn; pjmedia_sdp_rtpmap *rtpmap; int local_fmtp_mode = 0, rem_fmtp_mode = 0; - unsigned i, pt; + unsigned i, pt, fmti; pj_status_t status; @@ -248,17 +248,40 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( } - /* And codec must be numeric! */ + /* Get the payload number for receive channel. */ + /* + Previously we used to rely on fmt[0] being the selected codec, + but some UA sends telephone-event as fmt[0] and this would + cause assert failure below. + + Thanks Chris Hamilton for this patch. + + // And codec must be numeric! if (!pj_isdigit(*local_m->desc.fmt[0].ptr) || !pj_isdigit(*rem_m->desc.fmt[0].ptr)) { return PJMEDIA_EINVALIDPT; } - /* Get the payload number for receive channel. */ pt = pj_strtoul(&local_m->desc.fmt[0]); pj_assert(PJMEDIA_RTP_PT_TELEPHONE_EVENTS==0 || pt != PJMEDIA_RTP_PT_TELEPHONE_EVENTS); + */ + + /* This is to suppress MSVC warning about uninitialized var */ + pt = 0; + + /* Find the first codec which is not telephone-event */ + for ( fmti = 0; fmti < local_m->desc.fmt_count; ++fmti ) { + if ( !pj_isdigit(*local_m->desc.fmt[fmti].ptr) ) + return PJMEDIA_EINVALIDPT; + pt = pj_strtoul(&local_m->desc.fmt[fmti]); + if ( PJMEDIA_RTP_PT_TELEPHONE_EVENTS == 0 || + pt != PJMEDIA_RTP_PT_TELEPHONE_EVENTS ) + break; + } + if ( fmti >= local_m->desc.fmt_count ) + return PJMEDIA_EINVALIDPT; /* Get codec info. * For static payload types, get the info from codec manager. @@ -271,7 +294,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( has_rtpmap = PJ_TRUE; attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP, - &local_m->desc.fmt[0]); + &local_m->desc.fmt[fmti]); if (attr == NULL) { has_rtpmap = PJ_FALSE; } @@ -284,7 +307,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( /* Build codec format info: */ if (has_rtpmap) { si->fmt.type = si->type; - si->fmt.pt = pj_strtoul(&local_m->desc.fmt[0]); + si->fmt.pt = pj_strtoul(&local_m->desc.fmt[fmti]); pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name); si->fmt.clock_rate = rtpmap->clock_rate; @@ -322,7 +345,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( } else { attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP, - &local_m->desc.fmt[0]); + &local_m->desc.fmt[fmti]); if (attr == NULL) return PJMEDIA_EMISSINGRTPMAP; @@ -333,7 +356,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( /* Build codec format info: */ si->fmt.type = si->type; - si->fmt.pt = pj_strtoul(&local_m->desc.fmt[0]); + si->fmt.pt = pj_strtoul(&local_m->desc.fmt[fmti]); pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name); si->fmt.clock_rate = rtpmap->clock_rate; @@ -356,7 +379,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( } /* Get fmtp mode= param in local SDP, if any */ - get_fmtp_mode(local_m, &local_m->desc.fmt[0], &local_fmtp_mode); + get_fmtp_mode(local_m, &local_m->desc.fmt[fmti], &local_fmtp_mode); /* Determine payload type for outgoing channel, by finding * dynamic payload type in remote SDP that matches the answer. diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index 2441f8ed..b0e420eb 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -708,6 +708,9 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) if (status != PJ_SUCCESS) pjsua_perror(THIS_FILE, "Error answering session", status); + /* Note that inv may be invalid if 200/OK has caused error in + * starting the media. + */ PJ_LOG(4,(THIS_FILE, "Disconnecting replaced call %d", replaced_call->index)); @@ -1035,6 +1038,14 @@ PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id, return status; } + /* Call might have been disconnected if application is answering with + * 200/OK and the media failed to start. + */ + if (call->inv == NULL) { + pjsip_dlg_dec_lock(dlg); + return PJSIP_ESESSIONTERMINATED; + } + /* Add additional headers etc */ pjsua_process_msg_data( tdata, msg_data); -- cgit v1.2.3