summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-12-17 14:28:18 +0000
committerBenny Prijono <bennylp@teluu.com>2008-12-17 14:28:18 +0000
commit30d11975f4123b0dfd06b1ba6d36b8e0bbe09a51 (patch)
tree401cad084f7d2fab6935488a5fcf575f5384bbac
parentb6529acff90535f3f54b57d093bae7bc90139bff (diff)
Ticket 684: protect the memory allocation for TX packet with try/catch, and fixed various transmit data buffer leaks when transmission fails immediately
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2380 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip-apps/src/pjsua/pjsua_app.c3
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c5
-rw-r--r--pjsip/src/pjsip/sip_dialog.c18
-rw-r--r--pjsip/src/pjsip/sip_transport.c13
-rw-r--r--pjsip/src/pjsip/sip_util.c6
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c31
6 files changed, 64 insertions, 12 deletions
diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c
index 13f948fa..e8e88750 100644
--- a/pjsip-apps/src/pjsua/pjsua_app.c
+++ b/pjsip-apps/src/pjsua/pjsua_app.c
@@ -2187,6 +2187,9 @@ static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
/* Start ringback */
ring_start(call_id);
+ if (current_call==PJSUA_INVALID_ID)
+ current_call = call_id;
+
if (app_config.auto_answer > 0) {
pjsua_call_answer(call_id, app_config.auto_answer, NULL, NULL);
}
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
index e1bcd0df..6e31d25f 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -2814,6 +2814,11 @@ static void inv_on_state_null( pjsip_inv_session *inv, pjsip_event *e)
if (tsx->status_code > 100)
inv_set_state(inv, PJSIP_INV_STATE_EARLY, e);
break;
+ case PJSIP_TSX_STATE_TERMINATED:
+ /* there is a failure in sending response. */
+ inv_set_cause(inv, tsx->status_code, &tsx->status_text);
+ inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
+ break;
default:
inv_on_state_incoming(inv, e);
break;
diff --git a/pjsip/src/pjsip/sip_dialog.c b/pjsip/src/pjsip/sip_dialog.c
index 6c6b2b3a..0d6e6d2c 100644
--- a/pjsip/src/pjsip/sip_dialog.c
+++ b/pjsip/src/pjsip/sip_dialog.c
@@ -540,6 +540,7 @@ PJ_DEF(pj_status_t) pjsip_dlg_create_uas( pjsip_user_agent *ua,
on_error:
if (tsx) {
pjsip_tsx_terminate(tsx, 500);
+ pj_assert(dlg->tsx_count>0);
--dlg->tsx_count;
}
@@ -1412,6 +1413,14 @@ PJ_DEF(pj_status_t) pjsip_dlg_send_response( pjsip_dialog *dlg,
/* Ask transaction to send the response */
status = pjsip_tsx_send_msg(tsx, tdata);
+ /* This function must decrement transmit data request counter
+ * regardless of the operation status. The transaction only
+ * decrements the counter if the operation is successful.
+ */
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ }
+
pjsip_dlg_dec_lock(dlg);
return status;
@@ -1898,7 +1907,14 @@ void pjsip_dlg_on_tsx_state( pjsip_dialog *dlg,
}
- if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
+ /* It is possible that the transaction is terminated and this function
+ * is called while we're calling on_tsx_state(). So only decrement
+ * the tsx_count if we're still attached to the transaction.
+ */
+ if (tsx->state == PJSIP_TSX_STATE_TERMINATED &&
+ tsx->mod_data[dlg->ua->id] == dlg)
+ {
+ pj_assert(dlg->tsx_count>0);
--dlg->tsx_count;
tsx->mod_data[dlg->ua->id] = NULL;
}
diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
index 9727858b..15f39dec 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -568,8 +568,17 @@ static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata)
{
/* Allocate buffer if necessary. */
if (tdata->buf.start == NULL) {
- tdata->buf.start = (char*)
- pj_pool_alloc( tdata->pool, PJSIP_MAX_PKT_LEN);
+ PJ_USE_EXCEPTION;
+
+ PJ_TRY {
+ tdata->buf.start = (char*)
+ pj_pool_alloc(tdata->pool, PJSIP_MAX_PKT_LEN);
+ }
+ PJ_CATCH_ANY {
+ return PJ_ENOMEM;
+ }
+ PJ_END
+
tdata->buf.cur = tdata->buf.start;
tdata->buf.end = tdata->buf.start + PJSIP_MAX_PKT_LEN;
}
diff --git a/pjsip/src/pjsip/sip_util.c b/pjsip/src/pjsip/sip_util.c
index d46d85be..a966ea3c 100644
--- a/pjsip/src/pjsip/sip_util.c
+++ b/pjsip/src/pjsip/sip_util.c
@@ -1673,8 +1673,12 @@ PJ_DEF(pj_status_t) pjsip_endpt_respond_stateless( pjsip_endpoint *endpt,
/* Send! */
status = pjsip_endpt_send_response( endpt, &res_addr, tdata, NULL, NULL );
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ return status;
+ }
- return status;
+ return PJ_SUCCESS;
}
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index 5b6b8e66..e0d0eb8f 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -909,12 +909,6 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
update_remote_nat_type(call, remote_sdp);
}
- /* Create and attach pjsua_var data to the dialog: */
- call->inv = inv;
-
- dlg->mod_data[pjsua_var.mod.id] = call;
- inv->mod_data[pjsua_var.mod.id] = call;
-
/* If account is locked to specific transport, then lock dialog
* to this transport too.
*/
@@ -925,7 +919,13 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
pjsip_dlg_set_transport(dlg, &tp_sel);
}
- /* Must answer with some response to initial INVITE.
+ /* Must answer with some response to initial INVITE. We'll do this before
+ * attaching the call to the invite session/dialog, so that the application
+ * will not get notification about this event (on another scenario, it is
+ * also possible that inv_send_msg() fails and causes the invite session to
+ * be disconnected. If we have the call attached at this time, this will
+ * cause the disconnection callback to be called before on_incoming_call()
+ * callback is called, which is not right).
*/
status = pjsip_inv_initial_answer(inv, rdata,
100, NULL, NULL, &response);
@@ -943,9 +943,17 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
status = pjsip_inv_send_msg(inv, response);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to send 100 response", status);
+ PJSUA_UNLOCK();
+ return PJ_TRUE;
}
}
+ /* Create and attach pjsua_var data to the dialog: */
+ call->inv = inv;
+
+ dlg->mod_data[pjsua_var.mod.id] = call;
+ inv->mod_data[pjsua_var.mod.id] = call;
+
++pjsua_var.call_cnt;
@@ -3725,10 +3733,17 @@ static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv,
pjsip_transaction *tsx,
pjsip_event *e)
{
- pjsua_call *call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
+ pjsua_call *call;
PJSUA_LOCK();
+ call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
+
+ if (call == NULL) {
+ PJSUA_UNLOCK();
+ return;
+ }
+
/* Notify application callback first */
if (pjsua_var.ua_cfg.cb.on_call_tsx_state) {
(*pjsua_var.ua_cfg.cb.on_call_tsx_state)(call->index, tsx, e);