diff options
author | Benny Prijono <bennylp@teluu.com> | 2007-06-20 10:03:46 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2007-06-20 10:03:46 +0000 |
commit | a73bec4fabd296d54db391af0a29a97c5a149e2a (patch) | |
tree | 053eb1a8c0deae0ae278883e4b6d592a262dd1c1 /pjsip | |
parent | ff591488bfa7b642ae00ab48cff03129f6c71ae1 (diff) |
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
Diffstat (limited to 'pjsip')
-rw-r--r-- | pjsip/include/pjsip-ua/sip_inv.h | 21 | ||||
-rw-r--r-- | pjsip/src/pjsip-ua/sip_inv.c | 58 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_call.c | 53 |
3 files changed, 124 insertions, 8 deletions
diff --git a/pjsip/include/pjsip-ua/sip_inv.h b/pjsip/include/pjsip-ua/sip_inv.h index 3a144f80..e74abfac 100644 --- a/pjsip/include/pjsip-ua/sip_inv.h +++ b/pjsip/include/pjsip-ua/sip_inv.h @@ -149,7 +149,10 @@ typedef struct pjsip_inv_callback /** * This callback is called when the invite session has received * new offer from peer. Application can inspect the remote offer - * in "offer". + * in "offer", and set the SDP answer with #pjsip_inv_set_sdp_answer(). + * When the application sends a SIP message to send the answer, + * this SDP answer will be negotiated with the offer, and the result + * will be sent with the SIP message. * * @param inv The invite session. * @param offer Remote offer. @@ -158,6 +161,22 @@ typedef struct pjsip_inv_callback const pjmedia_sdp_session *offer); /** + * This callback is optional, and it is used to ask the application + * to create a fresh offer, when the invite session has received + * re-INVITE without offer. This offer then will be sent in the + * 200/OK response to the re-INVITE request. + * + * If application doesn't implement this callback, the invite session + * will send the currently active SDP as the offer. + * + * @param inv The invite session. + * @param p_offer Pointer to receive the SDP offer created by + * application. + */ + void (*on_create_offer)(pjsip_inv_session *inv, + pjmedia_sdp_session **p_offer); + + /** * This callback is called after SDP offer/answer session has completed. * The status argument specifies the status of the offer/answer, * as returned by pjmedia_sdp_neg_negotiate(). 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 @@ -50,6 +50,12 @@ 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: * - incoming REFER request. @@ -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; @@ -2295,6 +2302,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. */ |