From a73bec4fabd296d54db391af0a29a97c5a149e2a Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Wed, 20 Jun 2007 10:03:46 +0000 Subject: More on ticket #399: a)send full offer on 200/OK response when re-INVITE does not have SDP, b) added on_create_offer() callback, c) handle some error cases git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1379 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/src/pjsip-ua/sip_inv.c | 58 +++++++++++++++++++++++++++++++++++----- pjsip/src/pjsua-lib/pjsua_call.c | 53 ++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 7 deletions(-) (limited to 'pjsip/src') diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c index 984501f6..c26c8bce 100644 --- a/pjsip/src/pjsip-ua/sip_inv.c +++ b/pjsip/src/pjsip-ua/sip_inv.c @@ -1225,8 +1225,13 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv, /* MUST NOT do multiple SDP offer/answer in a single transaction. */ - if (tsx_inv_data->sdp_done) + if (tsx_inv_data->sdp_done) { + if (rdata->msg_info.msg->body) { + PJ_LOG(4,(inv->obj_name, "SDP negotiation done, message " + "body is ignored")); + } return PJ_SUCCESS; + } /* Check if SDP is present in the message. */ @@ -1383,11 +1388,19 @@ static pj_status_t process_answer( pjsip_inv_session *inv, } else if (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO && pjmedia_sdp_neg_has_local_answer(inv->neg) ) { + struct tsx_inv_data *tsx_inv_data; + + /* Get invite session's transaction data */ + tsx_inv_data = (struct tsx_inv_data*) + inv->invite_tsx->mod_data[mod_inv.mod.id]; status = inv_negotiate_sdp(inv); if (status != PJ_SUCCESS) return status; + /* Mark this transaction has having SDP offer/answer done. */ + tsx_inv_data->sdp_done = 1; + status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp); } } @@ -2503,12 +2516,33 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e) if (rdata->msg_info.msg->body != NULL) { status = process_answer(inv, 200, tdata, NULL); } else { - const pjmedia_sdp_session *active_sdp; - status = pjmedia_sdp_neg_send_local_offer(dlg->pool, - inv->neg, - &active_sdp); - if (status == PJ_SUCCESS) { - tdata->msg->body = create_sdp_body(tdata->pool, active_sdp); + /* INVITE does not have SDP. + * If on_create_offer() callback is implemented, ask app. + * to generate an offer, otherwise just send active local + * SDP to signal that nothing gets modified. + */ + pjmedia_sdp_session *sdp = NULL; + + if (mod_inv.cb.on_create_offer) { + (*mod_inv.cb.on_create_offer)(inv, &sdp); + if (sdp) { + status = pjmedia_sdp_neg_modify_local_offer(dlg->pool, + inv->neg, + sdp); + } + } + + if (sdp == NULL) { + const pjmedia_sdp_session *active_sdp = NULL; + status = pjmedia_sdp_neg_send_local_offer(dlg->pool, + inv->neg, + &active_sdp); + if (status == PJ_SUCCESS) + sdp = (pjmedia_sdp_session*) active_sdp; + } + + if (sdp) { + tdata->msg->body = create_sdp_body(tdata->pool, sdp); } } @@ -2604,6 +2638,16 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e) */ inv_set_cause(inv, tsx->status_code, &tsx->status_text); inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); + + } else if (tsx->status_code >= 300 && tsx->status_code < 700) { + + pjmedia_sdp_neg_state neg_state; + + /* Outgoing INVITE transaction has failed, cancel SDP nego */ + neg_state = pjmedia_sdp_neg_get_state(inv->neg); + if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) { + pjmedia_sdp_neg_cancel_offer(inv->neg); + } } } } diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index 247c3085..e362679d 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -49,6 +49,12 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv, static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, const pjmedia_sdp_session *offer); +/* + * Called to generate new offer. + */ +static void pjsua_call_on_create_offer(pjsip_inv_session *inv, + pjmedia_sdp_session **offer); + /* * This callback is called when transaction state has changed in INVITE * session. We use this to trap: @@ -118,6 +124,7 @@ pj_status_t pjsua_call_subsys_init(const pjsua_config *cfg) inv_cb.on_new_session = &pjsua_call_on_forked; inv_cb.on_media_update = &pjsua_call_on_media_update; inv_cb.on_rx_offer = &pjsua_call_on_rx_offer; + inv_cb.on_create_offer = &pjsua_call_on_create_offer; inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed; @@ -2294,6 +2301,52 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, } +/* + * Called to generate new offer. + */ +static void pjsua_call_on_create_offer(pjsip_inv_session *inv, + pjmedia_sdp_session **offer) +{ + pjsua_call *call; + pj_status_t status; + + PJSUA_LOCK(); + + call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; + + /* See if we've put call on hold. */ + if (call->media_st == PJSUA_CALL_MEDIA_LOCAL_HOLD) { + PJ_LOG(4,(THIS_FILE, + "Call %d: call is on-hold locally, creating inactive SDP ", + call->index)); + status = create_inactive_sdp( call, offer ); + } else { + + PJ_LOG(4,(THIS_FILE, "Call %d: asked to send a new offer", + call->index)); + + /* Init media channel */ + status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Error initializing media channel", status); + PJSUA_UNLOCK(); + return; + } + + status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, offer); + } + + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Unable to create local SDP", status); + PJSUA_UNLOCK(); + return; + } + + + PJSUA_UNLOCK(); +} + + /* * Callback called by event framework when the xfer subscription state * has changed. -- cgit v1.2.3