Commit 9ef5f686 authored by Pekka Pessi's avatar Pekka Pessi
Browse files

nua_session.c: destroying invite transaction only after nua_i_invite is sent

Added nua_client_request_clean(), nua_invite_client_should_ack().

darcs-hash:20080813170333-db55f-89fa2c3bcddca312b2db81b741ada14ef69a9740.gz
parent d07e9d10
......@@ -296,6 +296,7 @@ struct nua_client_request
unsigned cr_dialog:1; /**< Request can initiate dialog */
/* Current state */
unsigned cr_acked:1; /**< Final response to the request has been ACKed */
unsigned cr_waiting:1; /**< Request is waiting */
unsigned cr_challenged:1; /**< Request was challenged */
unsigned cr_wait_for_cred:1; /**< Request is pending authentication */
......@@ -523,7 +524,6 @@ void *nua_private_client_request(nua_client_request_t const *cr)
}
void nua_client_request_complete(nua_client_request_t *);
void nua_client_request_destroy(nua_client_request_t *);
int nua_client_request_queue(nua_client_request_t *cr);
......@@ -533,8 +533,8 @@ su_inline int nua_client_is_queued(nua_client_request_t const *cr)
return cr && cr->cr_prev;
}
nua_client_request_t *nua_client_request_remove(nua_client_request_t *cr);
void nua_client_request_remove(nua_client_request_t *cr);
void 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)
......
......@@ -197,6 +197,7 @@ static void signal_call_state_change(nua_handle_t *nh,
int status, char const *phrase,
enum nua_callstate next_state);
static int nua_invite_client_should_ack(nua_client_request_t const *cr);
static int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags);
static int nua_invite_client_complete(nua_client_request_t *cr);
......@@ -247,15 +248,6 @@ void nua_session_usage_remove(nua_handle_t *nh,
nua_client_request_t *cr, *cr_next;
nua_server_request_t *sr;
cr = du->du_cr;
if (cr != cr0 && cr && cr->cr_orq && cr->cr_status >= 200 &&
cr->cr_method == sip_method_invite) {
ss->ss_reporting = 1;
nua_invite_client_ack(cr, NULL);
ss->ss_reporting = 0;
}
/* Destroy queued INVITE transactions */
for (cr = ds->ds_cr; cr; cr = cr_next) {
cr_next = cr->cr_next;
......@@ -266,6 +258,13 @@ void nua_session_usage_remove(nua_handle_t *nh,
if (cr == cr0)
continue;
if (nua_invite_client_should_ack(cr)) {
ss->ss_reporting = 1;
nua_invite_client_ack(cr, NULL);
ss->ss_reporting = 0;
nua_client_request_clean(cr);
}
if (cr == du->du_cr && cr->cr_orq)
continue;
......@@ -1180,6 +1179,8 @@ int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e,
error = nua_invite_client_ack(cr, tags);
nua_client_request_clean(cr);
if (error < 0) {
if (ss->ss_reason == NULL)
ss->ss_reason = "SIP;cause=500;text=\"Internal Error\"";
......@@ -1230,7 +1231,6 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags)
assert(cr->cr_orq);
assert(cr->cr_method == sip_method_invite);
if (!ds->ds_leg) {
/* XXX - fix nua_dialog_usage_remove_at() instead! */
nta_outgoing_destroy(cr->cr_orq);
......@@ -1366,12 +1366,20 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags)
if (error == -1)
msg_destroy(msg);
nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL;
nua_client_request_remove(cr);
cr->cr_acked = 1; /* ... or we have at least tried */
return error;
}
static int
nua_invite_client_should_ack(nua_client_request_t const *cr)
{
return
cr && cr->cr_orq && !cr->cr_acked &&
200 <= cr->cr_status && cr->cr_status < 300;
}
/** Complete client request */
static int nua_invite_client_complete(nua_client_request_t *cr)
{
......@@ -1379,7 +1387,7 @@ static int nua_invite_client_complete(nua_client_request_t *cr)
/* Xyzzy */;
else if (cr->cr_status < 200)
nta_outgoing_cancel(cr->cr_orq);
else
else if (cr->cr_status < 300 && !cr->cr_acked)
nua_invite_client_ack(cr, NULL);
return 0;
......@@ -1560,10 +1568,13 @@ static int nua_session_usage_shutdown(nua_handle_t *nh,
case nua_callstate_completed:
case nua_callstate_ready:
if (cri && cri->cr_orq) {
if (cri->cr_status < 200)
if (cri->cr_status < 200) {
nua_client_create(nh, nua_r_cancel, &nua_cancel_client_methods, NULL);
else if (cri->cr_status < 300)
}
else if (cri->cr_status < 300 && !cri->cr_acked) {
nua_invite_client_ack(cri, NULL);
nua_client_request_clean(cri);
}
}
if (nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL) != 0)
break;
......@@ -1796,7 +1807,7 @@ static int nua_prack_client_report(nua_client_request_t *cr,
if (status < 200)
;
else if (du->du_cr && du->du_cr->cr_orq && du->du_cr->cr_status >= 200) {
else if (nua_invite_client_should_ack(du->du_cr)) {
/* There is an un-ACK-ed INVITE there */
assert(du->du_cr->cr_method == sip_method_invite);
if (NH_PGET(nh, auto_ack) ||
......@@ -1807,6 +1818,7 @@ static int nua_prack_client_report(nua_client_request_t *cr,
next_state = nua_callstate_ready;
else
next_state = nua_callstate_terminating;
nua_client_request_clean(du->du_cr);
}
}
......@@ -3300,7 +3312,7 @@ static int nua_update_client_report(nua_client_request_t *cr,
if (status < 200)
;
else if (du->du_cr && du->du_cr->cr_orq && du->du_cr->cr_status >= 200) {
else if (nua_invite_client_should_ack(du->du_cr)) {
/* There is an un-ACK-ed INVITE there */
assert(du->du_cr->cr_method == sip_method_invite);
......@@ -3311,6 +3323,7 @@ static int nua_update_client_report(nua_client_request_t *cr,
next_state = nua_callstate_ready;
else
next_state = nua_callstate_terminating;
nua_client_request_clean(du->du_cr);
}
}
......
......@@ -2092,13 +2092,17 @@ int nua_client_request_queue(nua_client_request_t *cr)
return queued;
}
nua_client_request_t *nua_client_request_remove(nua_client_request_t *cr)
void nua_client_request_remove(nua_client_request_t *cr)
{
if (cr->cr_prev)
if ((*cr->cr_prev = cr->cr_next))
cr->cr_next->cr_prev = cr->cr_prev;
cr->cr_prev = NULL, cr->cr_next = NULL;
return cr;
}
void nua_client_request_clean(nua_client_request_t *cr)
{
nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL, cr->cr_acked = 0;
}
void nua_client_request_complete(nua_client_request_t *cr)
......@@ -3106,13 +3110,13 @@ int nua_base_client_response(nua_client_request_t *cr,
if (status < 200 ||
/* Un-ACKed 2XX response to INVITE */
(method == sip_method_invite && status < 300 && cr->cr_orq)) {
(method == sip_method_invite && status < 300 && !cr->cr_acked)) {
cr->cr_reporting = 0, nh->nh_ds->ds_reporting = 0;
return 1;
}
if (cr->cr_orq)
nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL;
nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL, cr->cr_acked = 0;
du = cr->cr_usage;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment