diff options
author | Benny Prijono <bennylp@teluu.com> | 2008-12-17 14:28:18 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2008-12-17 14:28:18 +0000 |
commit | 30d11975f4123b0dfd06b1ba6d36b8e0bbe09a51 (patch) | |
tree | 401cad084f7d2fab6935488a5fcf575f5384bbac /pjsip | |
parent | b6529acff90535f3f54b57d093bae7bc90139bff (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
Diffstat (limited to 'pjsip')
-rw-r--r-- | pjsip/src/pjsip-ua/sip_inv.c | 5 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_dialog.c | 18 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_transport.c | 13 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_util.c | 6 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_call.c | 31 |
5 files changed, 61 insertions, 12 deletions
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); |