Commit 1b6c420e authored by Pekka Pessi's avatar Pekka Pessi

nua: redirecting automatically with 305 (bug #1676445)

The request is redirected through a proxy after a 305 response has been
received. Note that the outbound proxy configured with NUTAG_PROXY() is
still used.

darcs-hash:20070326162608-55b16-104bbfb5021d6acd72bb30fd38176089036451ff.gz
parent c0a9e10b
......@@ -2410,14 +2410,31 @@ int nua_base_client_check_restart(nua_client_request_t *cr,
/* XXX - handle Retry-After */
if (status == 302) {
if (status == 302 || status == 305) {
sip_route_t r[1];
if (!can_redirect(sip->sip_contact, cr->cr_method))
return 0;
if (nua_client_set_target(cr, sip->sip_contact->m_url) >= 0)
return nua_client_restart(cr, 100, "Redirected");
switch (status) {
case 302:
if (nua_client_set_target(cr, sip->sip_contact->m_url) >= 0)
return nua_client_restart(cr, 100, "Redirected");
break;
case 305:
sip_route_init(r);
*r->r_url = *sip->sip_contact->m_url;
if (sip_add_dup(cr->cr_msg, cr->cr_sip, (sip_header_t *)r) >= 0)
return nua_client_restart(cr, 100, "Redirected via a proxy");
break;
default:
break;
}
}
if (status == 423) {
unsigned my_expires = 0;
......
......@@ -261,7 +261,7 @@ int test_reject_b(struct context *ctx)
/* ------------------------------------------------------------------------ */
int reject_302(CONDITION_PARAMS);
int reject_302(CONDITION_PARAMS), reject_305(CONDITION_PARAMS);
int reject_604(CONDITION_PARAMS);
/*
......@@ -281,6 +281,7 @@ int reject_604(CONDITION_PARAMS);
|<---604 Nowhere-----|
|--------ACK-------->|
*/
int reject_302(CONDITION_PARAMS)
{
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
......@@ -298,6 +299,33 @@ int reject_302(CONDITION_PARAMS)
SIPTAG_CONTACT(m), TAG_END());
}
return 0;
case nua_callstate_terminated:
if (call)
nua_handle_destroy(call->nh), call->nh = NULL;
ep->next_condition = reject_305;
return 0;
default:
return 0;
}
}
int reject_305(CONDITION_PARAMS)
{
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
save_event_in_list(ctx, event, ep, call);
switch (callstate(tags)) {
case nua_callstate_received:
{
sip_contact_t m[1];
*m = *ep->contact;
m->m_url->url_user = "305";
m->m_url->url_params = "lr=1";
RESPOND(ep, call, nh, SIP_305_USE_PROXY, SIPTAG_CONTACT(m), TAG_END());
}
return 0;
case nua_callstate_terminated:
if (call)
nua_handle_destroy(call->nh), call->nh = NULL;
......@@ -308,6 +336,7 @@ int reject_302(CONDITION_PARAMS)
}
}
int reject_604(CONDITION_PARAMS)
{
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
......@@ -338,6 +367,7 @@ int test_reject_302(struct context *ctx)
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e;
sip_t const *sip;
/* Make call reject-3 */
if (print_headings)
......@@ -388,6 +418,12 @@ int test_reject_302(struct context *ctx)
TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(is_offer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 100);
TEST(sip_object(e->data->e_msg)->sip_status->st_status, 305);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(is_offer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 180);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_proceeding); /* PROCEEDING */
......@@ -415,6 +451,18 @@ int test_reject_302(struct context *ctx)
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_invite);
TEST(e->data->e_status, 100);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_request);
TEST_S(sip->sip_request->rq_url->url_user, "302");
TEST_1(sip->sip_route);
TEST_S(sip->sip_route->r_url->url_user, "305");
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
......
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