summaryrefslogtreecommitdiff
path: root/pjsip/src
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2013-07-15 04:23:31 +0000
committerLiong Sauw Ming <ming@teluu.com>2013-07-15 04:23:31 +0000
commit551dc7de88217169f01624a64c4a20ded378c7d8 (patch)
treec22d1ebff97d68b00372fb024cc4ccbce5c481f3 /pjsip/src
parent8d9d6c3f11a8eac5204f2c4c18046e6d4dab18f3 (diff)
Re #817: Initial work for allowing application to respond to re-INVITE manually.
Patches integrated in this fix (with some modifications for adjustment to the current trunk): - sip_inv-on_rx_reinvite.patch Move the place where to call the callback so the callback will still be called when the re-invite contains no SDP - sdp_neg_cancel_remote_offer pjmedia_sdp_neg_cancel_remote_offer() is no longer necessary since pjmedia_sdp_neg_cancel_offer() can already handle that. Only integrate the chart for sdp negotiation doc. - sip_inv-terminate-reinvite-tsx-on-cancel - sip_inv-cancel_sdp_neg_on_sending_negative_reply_to_reinvite - pjsip-allow_cancel_reinvite git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4562 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src')
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c132
1 files changed, 118 insertions, 14 deletions
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
index 4f490f92..87aca6fe 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -1835,6 +1835,15 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,
if (pjmedia_sdp_neg_get_state(inv->neg) !=
PJMEDIA_SDP_NEG_STATE_WAIT_NEGO)
{
+ if (mod_inv.cb.on_rx_reinvite && inv->notify &&
+ msg->type == PJSIP_REQUEST_MSG &&
+ msg->line.req.method.id == PJSIP_INVITE_METHOD)
+ {
+ /* Do not return failure first, allow the application
+ * to set the answer in the on_rx_reinvite() callback.
+ */
+ return PJ_SUCCESS;
+ }
return PJ_EINVALIDOP;
}
@@ -1972,6 +1981,16 @@ static pj_status_t process_answer( pjsip_inv_session *inv,
}
}
+ /* Cancel SDP negotiation if this is a negative reply to a re-INVITE */
+ if (st_code >= 300 && inv->neg != NULL &&
+ inv->state == PJSIP_INV_STATE_CONFIRMED)
+ {
+ pjmedia_sdp_neg_state neg_state;
+ neg_state = pjmedia_sdp_neg_get_state(inv->neg);
+ if (neg_state == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER) {
+ pjmedia_sdp_neg_cancel_offer(inv->neg);
+ }
+ }
return PJ_SUCCESS;
}
@@ -2052,8 +2071,7 @@ on_return:
/*
- * Answer initial INVITE
- * Re-INVITE will be answered automatically, and will not use this function.
+ * Answer INVITE request.
*/
PJ_DEF(pj_status_t) pjsip_inv_answer( pjsip_inv_session *inv,
int st_code,
@@ -2279,6 +2297,62 @@ PJ_DEF(pj_status_t) pjsip_inv_end_session( pjsip_inv_session *inv,
return PJ_SUCCESS;
}
+/*
+ * Cancel re-INVITE transaction.
+ */
+PJ_DEF(pj_status_t) pjsip_inv_cancel_reinvite( pjsip_inv_session *inv,
+ pjsip_tx_data **p_tdata )
+{
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ /* Verify arguments. */
+ PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL);
+
+ pj_log_push_indent();
+
+ /* Create appropriate message. */
+ switch (inv->state) {
+ case PJSIP_INV_STATE_CONFIRMED:
+ /* MUST have the original UAC INVITE transaction */
+ PJ_ASSERT_RETURN(inv->invite_tsx != NULL, PJ_EBUG);
+
+ /* CANCEL should only be called when we have received a
+ * provisional response.
+ */
+ if (inv->invite_tsx->status_code < 100) {
+ inv->cancelling = PJ_TRUE;
+ inv->pending_cancel = PJ_TRUE;
+ *p_tdata = NULL;
+ PJ_LOG(4, (inv->obj_name, "Delaying CANCEL since no "
+ "provisional response is received yet"));
+ pj_log_pop_indent();
+ return PJ_SUCCESS;
+ }
+
+ status = pjsip_endpt_create_cancel(inv->dlg->endpt,
+ inv->invite_tsx->last_tx,
+ &tdata);
+ if (status != PJ_SUCCESS) {
+ pj_log_pop_indent();
+ return status;
+ }
+ break;
+
+ default:
+ /* We cannot send CANCEL to a re-INVITE if the INVITE session is
+ * not confirmed.
+ */
+ pj_log_pop_indent();
+ return PJ_EINVALIDOP;
+ }
+
+ pj_log_pop_indent();
+
+ *p_tdata = tdata;
+ return PJ_SUCCESS;
+}
+
/* Following redirection recursion, get next target from the target set and
* notify user.
*
@@ -4082,17 +4156,9 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e)
{
/*
- * Handle strandled incoming CANCEL.
+ * Handle strandled incoming CANCEL or CANCEL for re-INVITE
*/
- pjsip_rx_data *rdata = e->body.tsx_state.src.rdata;
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- status = pjsip_dlg_create_response(dlg, rdata, 200, NULL, &tdata);
- if (status != PJ_SUCCESS) return;
-
- status = pjsip_dlg_send_response(dlg, tsx, tdata);
- if (status != PJ_SUCCESS) return;
+ inv_respond_incoming_cancel(inv, tsx, e);
} else if (tsx->role == PJSIP_ROLE_UAS &&
tsx->state == PJSIP_TSX_STATE_TRYING &&
@@ -4228,7 +4294,7 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
pjsip_rx_data *rdata = e->body.tsx_state.src.rdata;
pjsip_tx_data *tdata;
pj_status_t status;
- pjsip_rdata_sdp_info *sdp_info;
+ pjsip_rdata_sdp_info *sdp_info = NULL;
pjsip_status_code st_code;
/* Check if we have INVITE pending. */
@@ -4301,6 +4367,29 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
/* Process SDP in incoming message. */
status = inv_check_sdp_in_incoming_msg(inv, tsx, rdata);
+ if (status == PJ_SUCCESS && mod_inv.cb.on_rx_reinvite &&
+ inv->notify)
+ {
+ sdp_info = pjsip_rdata_get_sdp_info(rdata);
+ if ((*mod_inv.cb.on_rx_reinvite)
+ (inv, sdp_info->sdp, rdata) == PJ_SUCCESS)
+ {
+ /* Application will send its own response.
+ * Our job is done. */
+ return;
+ }
+
+ /* If application lets us answer the re-INVITE,
+ * application must set the SDP answer with
+ * #pjsip_inv_set_sdp_answer().
+ */
+ if (pjmedia_sdp_neg_get_state(inv->neg) !=
+ PJMEDIA_SDP_NEG_STATE_WAIT_NEGO)
+ {
+ status = PJ_EINVALIDOP;
+ }
+ }
+
if (status != PJ_SUCCESS) {
/* Not Acceptable */
@@ -4342,7 +4431,8 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
/* If the INVITE request has SDP body, send answer.
* Otherwise generate offer from local active SDP.
*/
- sdp_info = pjsip_rdata_get_sdp_info(rdata);
+ if (!sdp_info)
+ sdp_info = pjsip_rdata_get_sdp_info(rdata);
if (sdp_info->sdp != NULL) {
status = process_answer(inv, 200, tdata, NULL);
} else {
@@ -4459,6 +4549,20 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
/* Save pending invite transaction */
inv->invite_tsx = tsx;
+ } else if (tsx->state == PJSIP_TSX_STATE_PROCEEDING) {
+
+ /* CANCEL the re-INVITE if necessary */
+ if (inv->pending_cancel) {
+ pj_status_t status;
+ pjsip_tx_data *cancel;
+
+ inv->pending_cancel = PJ_FALSE;
+
+ status = pjsip_inv_cancel_reinvite(inv, &cancel);
+ if (status == PJ_SUCCESS && cancel)
+ status = pjsip_inv_send_msg(inv, cancel);
+ }
+
} else if (tsx->state == PJSIP_TSX_STATE_TERMINATED &&
tsx->status_code/100 == 2)
{