提交 ef020e60 authored 作者: Michael Jerris's avatar Michael Jerris

Wed Sep 3 14:20:29 EDT 2008 Pekka Pessi <first.last@nokia.com>

  * nua: added reference counting for client-side transactions



git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9421 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 a2740a96
Wed Sep 3 14:29:03 EDT 2008
Wed Sep 3 14:29:36 EDT 2008
......@@ -354,12 +354,12 @@ void nua_dialog_usage_remove(nua_owner_t *own,
*
* Zap dialog state (leg, tag and route) if no usages remain.
*/
static
void nua_dialog_usage_remove_at(nua_owner_t *own,
nua_dialog_state_t *ds,
nua_dialog_usage_t **at,
nua_client_request_t *cr0,
nua_server_request_t *sr0)
static void
nua_dialog_usage_remove_at(nua_owner_t *own,
nua_dialog_state_t *ds,
nua_dialog_usage_t **at,
nua_client_request_t *cr0,
nua_server_request_t *sr0)
{
if (*at) {
nua_dialog_usage_t *du = *at;
......@@ -376,17 +376,9 @@ void nua_dialog_usage_remove_at(nua_owner_t *own,
o ? " with event " : "", o ? o->o_type :""));
du->du_class->usage_remove(own, ds, du, cr0, sr0);
/* Destroy saved client request */
if (cr0 != du->du_cr && nua_client_is_bound(du->du_cr)) {
nua_client_bind(cr = du->du_cr, NULL);
if (nua_client_is_queued(cr))
nua_client_request_complete(cr);
else if (nua_client_is_reporting(cr))
;
else
nua_client_request_destroy(cr);
}
/* Clean reference to saved client request */
if (du->du_cr)
nua_client_bind(du->du_cr, NULL);
/* Clean references from queued client requests */
for (cr = ds->ds_cr; cr; cr = cr_next) {
......@@ -395,6 +387,7 @@ void nua_dialog_usage_remove_at(nua_owner_t *own,
cr->cr_usage = NULL;
}
/* Clean references from queued server requests */
for (sr = ds->ds_sr; sr; sr = sr_next) {
sr_next = sr->sr_next;
if (sr->sr_usage == du) {
......
......@@ -276,6 +276,8 @@ struct nua_client_request
unsigned short cr_retry_count; /**< Retry count for this request */
uint32_t cr_seq;
unsigned cr_refs; /**< References to client request */
/* Flags used with offer-answer */
unsigned short cr_answer_recv; /**< Recv answer in response
......@@ -300,7 +302,6 @@ struct nua_client_request
unsigned cr_waiting:1; /**< Request is waiting */
unsigned cr_challenged:1; /**< Request was challenged */
unsigned cr_wait_for_cred:1; /**< Request is pending authentication */
unsigned cr_wait_for_timer:1; /**< Request is waiting for a timer to expire */
unsigned cr_restarting:1; /**< Request is being restarted */
unsigned cr_reporting:1; /**< Reporting in progress */
unsigned cr_terminating:1; /**< Request terminates the usage */
......@@ -523,8 +524,23 @@ void *nua_private_client_request(nua_client_request_t const *cr)
return (void *)(cr + 1);
}
void nua_client_request_complete(nua_client_request_t *);
void nua_client_request_destroy(nua_client_request_t *);
nua_client_request_t *nua_client_request_ref(nua_client_request_t *);
int nua_client_request_unref(nua_client_request_t *);
#if HAVE_MEMLEAK_LOG
#define nua_client_request_ref(cr) \
nua_client_request_ref_by((cr), __FILE__, __LINE__, __func__)
#define nua_client_request_unref(cr) \
nua_client_request_unref_by((cr), __FILE__, __LINE__, __func__)
nua_client_request_t *nua_client_request_ref_by(nua_client_request_t *,
char const *file, unsigned line,
char const *who);
int nua_client_request_unref_by(nua_client_request_t *,
char const *file, unsigned line, char const *who);
#endif
int nua_client_request_queue(nua_client_request_t *cr);
......@@ -533,8 +549,8 @@ su_inline int nua_client_is_queued(nua_client_request_t const *cr)
return cr && cr->cr_prev;
}
void nua_client_request_remove(nua_client_request_t *cr);
void nua_client_request_clean(nua_client_request_t *cr);
int nua_client_request_remove(nua_client_request_t *cr);
int nua_client_request_clean(nua_client_request_t *cr);
int nua_client_bind(nua_client_request_t *cr, nua_dialog_usage_t *du);
su_inline int nua_client_is_bound(nua_client_request_t const *cr)
......
......@@ -276,7 +276,7 @@ void nua_session_usage_remove(nua_handle_t *nh,
NULL);
}
nua_client_request_destroy(cr);
nua_client_request_remove(cr);
cr_next = ds->ds_cr;
}
......@@ -1177,9 +1177,9 @@ int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e,
soa_set_params(nh->nh_soa, TAG_NEXT(tags));
}
error = nua_invite_client_ack(cr, tags);
nua_client_request_ref(cr);
nua_client_request_clean(cr);
error = nua_invite_client_ack(cr, tags);
if (error < 0) {
if (ss->ss_reason == NULL)
......@@ -1195,8 +1195,7 @@ int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e,
else if (ss)
signal_call_state_change(nh, ss, 200, "ACK sent", nua_callstate_ready);
if (!nua_client_is_queued(cr) && !nua_client_is_bound(cr))
nua_client_request_destroy(cr);
nua_client_request_unref(cr);
nua_client_next_request(nh->nh_ds->ds_cr, 1);
......@@ -1233,7 +1232,8 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags)
if (!ds->ds_leg) {
/* XXX - fix nua_dialog_usage_remove_at() instead! */
nta_outgoing_destroy(cr->cr_orq);
nua_client_request_clean(cr);
nua_client_request_remove(cr);
return -1;
}
......@@ -1366,9 +1366,11 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags)
if (error == -1)
msg_destroy(msg);
nua_client_request_remove(cr);
cr->cr_acked = 1; /* ... or we have at least tried */
nua_client_request_clean(cr);
nua_client_request_remove(cr);
return error;
}
......@@ -1452,11 +1454,19 @@ static int nua_cancel_client_request(nua_client_request_t *cr,
return nua_client_return(cr, 481, "No transaction to CANCEL", msg);
}
assert(cr->cr_orq == NULL);
cr->cr_orq = nta_outgoing_tcancel(du->du_cr->cr_orq,
nua_client_orq_response, cr,
nua_client_orq_response,
nua_client_request_ref(cr),
TAG_NEXT(tags));
return cr->cr_orq ? 0 : -1;
if (cr->cr_orq == NULL) {
nua_client_request_unref(cr);
return -1;
}
return 0;
}
/** @NUA_EVENT nua_r_cancel
......@@ -3630,7 +3640,6 @@ static int nua_bye_client_init(nua_client_request_t *cr,
if (nh->nh_soa)
soa_terminate(nh->nh_soa, 0);
du->du_cr = NULL;
nua_client_bind(cr, du);
return 0;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论