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, ...@@ -2410,14 +2410,31 @@ int nua_base_client_check_restart(nua_client_request_t *cr,
/* XXX - handle Retry-After */ /* 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)) if (!can_redirect(sip->sip_contact, cr->cr_method))
return 0; return 0;
if (nua_client_set_target(cr, sip->sip_contact->m_url) >= 0) switch (status) {
return nua_client_restart(cr, 100, "Redirected"); 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) { if (status == 423) {
unsigned my_expires = 0; unsigned my_expires = 0;
......
...@@ -261,7 +261,7 @@ int test_reject_b(struct context *ctx) ...@@ -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); int reject_604(CONDITION_PARAMS);
/* /*
...@@ -281,6 +281,7 @@ int reject_604(CONDITION_PARAMS); ...@@ -281,6 +281,7 @@ int reject_604(CONDITION_PARAMS);
|<---604 Nowhere-----| |<---604 Nowhere-----|
|--------ACK-------->| |--------ACK-------->|
*/ */
int reject_302(CONDITION_PARAMS) int reject_302(CONDITION_PARAMS)
{ {
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR))) if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
...@@ -298,6 +299,33 @@ int reject_302(CONDITION_PARAMS) ...@@ -298,6 +299,33 @@ int reject_302(CONDITION_PARAMS)
SIPTAG_CONTACT(m), TAG_END()); SIPTAG_CONTACT(m), TAG_END());
} }
return 0; 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: case nua_callstate_terminated:
if (call) if (call)
nua_handle_destroy(call->nh), call->nh = NULL; nua_handle_destroy(call->nh), call->nh = NULL;
...@@ -308,6 +336,7 @@ int reject_302(CONDITION_PARAMS) ...@@ -308,6 +336,7 @@ int reject_302(CONDITION_PARAMS)
} }
} }
int reject_604(CONDITION_PARAMS) int reject_604(CONDITION_PARAMS)
{ {
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR))) if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
...@@ -338,6 +367,7 @@ int test_reject_302(struct context *ctx) ...@@ -338,6 +367,7 @@ int test_reject_302(struct context *ctx)
struct endpoint *a = &ctx->a, *b = &ctx->b; struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call; struct call *a_call = a->call, *b_call = b->call;
struct event *e; struct event *e;
sip_t const *sip;
/* Make call reject-3 */ /* Make call reject-3 */
if (print_headings) if (print_headings)
...@@ -388,6 +418,12 @@ int test_reject_302(struct context *ctx) ...@@ -388,6 +418,12 @@ int test_reject_302(struct context *ctx)
TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */ TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(is_offer_sent(e->data->e_tags)); TEST_1(is_offer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); 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(e->data->e_status, 180);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_proceeding); /* PROCEEDING */ TEST(callstate(e->data->e_tags), nua_callstate_proceeding); /* PROCEEDING */
...@@ -415,6 +451,18 @@ int test_reject_302(struct context *ctx) ...@@ -415,6 +451,18 @@ int test_reject_302(struct context *ctx)
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */ TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags)); TEST_1(is_offer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); 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(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); 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(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