summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2014-02-19 04:11:43 +0000
committerBenny Prijono <bennylp@teluu.com>2014-02-19 04:11:43 +0000
commit7c7dd8a6151a607ac7fda3da0a657fddd07be8d1 (patch)
tree96398ce995f9af19d04c35c6f85cf3efaf8d1b19
parentf9317b810877c3cab6bda8ea07dc94eb3ecb7c20 (diff)
Fixed #1738: Infinite loop when re-INVITE is received while adding new media
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4750 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/include/pjsua-lib/pjsua_internal.h6
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c24
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c14
-rw-r--r--pjsip/src/pjsua-lib/pjsua_vid.c10
4 files changed, 53 insertions, 1 deletions
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h
index dcf50209..ff414ea8 100644
--- a/pjsip/include/pjsua-lib/pjsua_internal.h
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -635,6 +635,12 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
const pjmedia_sdp_session *remote_sdp);
pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id);
+/*
+ * Error message when media operation is requested while another is in progress
+ */
+#define ERR_MEDIA_CHANGING " because another media operation is in progress"
+
+pj_bool_t pjsua_call_media_is_changing(pjsua_call *call);
pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
pjmedia_type type,
const pjsua_transport_config *tcfg,
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index 733bc599..db8bfa11 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -34,7 +34,6 @@
*/
#define LOCK_CODEC_MAX_RETRY 5
-
/*
* The INFO method.
*/
@@ -2392,6 +2391,12 @@ PJ_DEF(pj_status_t) pjsua_call_reinvite2(pjsua_call_id call_id,
if (status != PJ_SUCCESS)
goto on_return;
+ if (pjsua_call_media_is_changing(call)) {
+ PJ_LOG(1,(THIS_FILE, "Unable to reinvite" ERR_MEDIA_CHANGING));
+ status = PJ_EINVALIDOP;
+ goto on_return;
+ }
+
if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) {
PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed"));
status = PJSIP_ESESSIONSTATE;
@@ -2499,6 +2504,12 @@ PJ_DEF(pj_status_t) pjsua_call_update2(pjsua_call_id call_id,
if (status != PJ_SUCCESS)
goto on_return;
+ if (pjsua_call_media_is_changing(call)) {
+ PJ_LOG(1,(THIS_FILE, "Unable to send UPDATE" ERR_MEDIA_CHANGING));
+ status = PJ_EINVALIDOP;
+ goto on_return;
+ }
+
status = apply_call_setting(call, opt, NULL);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Failed to apply call setting", status);
@@ -3878,8 +3889,14 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
/* Supply candidate answer */
PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer",
call->index));
+
pj_log_push_indent();
+ if (pjsua_call_media_is_changing(call)) {
+ PJ_LOG(1,(THIS_FILE, "Unable to process offer" ERR_MEDIA_CHANGING));
+ goto on_return;
+ }
+
if (pjsua_var.ua_cfg.cb.on_call_rx_offer) {
pjsip_status_code code = PJSIP_SC_OK;
pjsua_call_setting opt = call->opt;
@@ -3969,6 +3986,11 @@ static void pjsua_call_on_create_offer(pjsip_inv_session *inv,
pj_log_push_indent();
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
+ if (pjsua_call_media_is_changing(call)) {
+ *offer = NULL;
+ PJ_LOG(1,(THIS_FILE, "Unable to create offer" ERR_MEDIA_CHANGING));
+ goto on_return;
+ }
/* See if we've put call on hold. */
if (call->local_hold) {
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index ab4c4bde..4beb821c 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -1304,6 +1304,20 @@ on_return:
return status;
}
+/* Determine if call's media is being changed, for example when video is being
+ * added. Then we can reject incoming re-INVITE, for example. This is the
+ * solution for https://trac.pjsip.org/repos/ticket/1738
+ */
+pj_bool_t pjsua_call_media_is_changing(pjsua_call *call)
+{
+ /* The problem in #1738 occurs because we do handle_events() loop while
+ * adding media, which could cause incoming re-INVITE to be processed and
+ * cause havoc. Since the handle_events() loop only happens while adding
+ * media, it is sufficient to only check if "prov > cnt" for now.
+ */
+ return call->med_prov_cnt > call->med_cnt;
+}
+
/* Initialize the media line */
pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
pjmedia_type type,
diff --git a/pjsip/src/pjsua-lib/pjsua_vid.c b/pjsip/src/pjsua-lib/pjsua_vid.c
index 0096acab..026942d1 100644
--- a/pjsip/src/pjsua-lib/pjsua_vid.c
+++ b/pjsip/src/pjsua-lib/pjsua_vid.c
@@ -1535,6 +1535,11 @@ static pj_status_t call_add_video(pjsua_call *call,
if (call->med_cnt == PJSUA_MAX_CALL_MEDIA)
return PJ_ETOOMANY;
+ if (pjsua_call_media_is_changing(call)) {
+ PJ_LOG(1,(THIS_FILE, "Unable to add video" ERR_MEDIA_CHANGING));
+ return PJ_EINVALIDOP;
+ }
+
/* Get active local SDP and clone it */
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &current_sdp);
if (status != PJ_SUCCESS)
@@ -1636,6 +1641,11 @@ static pj_status_t call_modify_video(pjsua_call *call,
pjmedia_sdp_session *sdp;
pj_status_t status;
+ if (pjsua_call_media_is_changing(call)) {
+ PJ_LOG(1,(THIS_FILE, "Unable to modify video" ERR_MEDIA_CHANGING));
+ return PJ_EINVALIDOP;
+ }
+
/* Verify and normalize media index */
if (med_idx == -1) {
int first_active;