Commit 2896cc7f authored by Pekka Pessi's avatar Pekka Pessi

nua: fixed the from header handling

The agent-level From header no longer overrides the From header set by
nua_invite() and friends.

Thanks to Fabio Margarido for keeping reporting about the problem.

darcs-hash:20071011172512-88462-71a1fdafc97d4165e4ec6e3d64f221544fb8cd18.gz
parent 5ccd273c
......@@ -196,6 +196,7 @@ int nua_stack_set_from(nua_t *nua, int initial, tagi_t const *tags)
sip_from_t const *from = NONE;
char const *str = NONE;
sip_from_t *f = NULL, f0[1];
int set;
char const *uicc_name = "default";
......@@ -220,11 +221,13 @@ int nua_stack_set_from(nua_t *nua, int initial, tagi_t const *tags)
f0->a_display = from->a_display;
*f0->a_url = *from->a_url;
f = sip_from_dup(nua->nua_home, f0);
set = 1;
}
else if (str && str != NONE) {
f = sip_from_make(nua->nua_home, str);
if (f)
*f0 = *f, f = f0, f->a_params = NULL;
set = 1;
}
else {
sip_contact_t const *m;
......@@ -236,11 +239,13 @@ int nua_stack_set_from(nua_t *nua, int initial, tagi_t const *tags)
*f0->a_url = *m->m_url;
f = sip_from_dup(nua->nua_home, f0);
}
set = 0;
}
if (!f)
return -1;
nua->nua_from_is_set = set;
*nua->nua_from = *f;
return 0;
}
......@@ -1148,7 +1153,6 @@ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags)
url_string_t const *url = NULL;
sip_to_t const *p_to = NULL;
char const *to_str = NULL;
sip_from_t from[1];
sip_from_t const *p_from = NULL;
char const *from_str = NULL;
nua_handle_t *identity = NULL;
......@@ -1210,10 +1214,8 @@ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags)
;
else if (from_str)
p_from = sip_from_make(tmphome, from_str);
else if (!p_from && nh->nh_nua->nua_from)
*from = *nh->nh_nua->nua_from, from->a_params = NULL, p_from = from;
else
p_from = SIP_NONE; /* XXX - why? */
p_from = SIP_NONE;
if (p_to)
;
......@@ -1553,8 +1555,8 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
if (nh->nh_ds->ds_local)
has_from = 1, *from = *nh->nh_ds->ds_local, from->a_params = NULL;
else
has_from = 0;
else /* if (nua->nua_from_is_set) */
has_from = 1, *from = *nua->nua_from;
media_params = soa_get_paramlist(nh->nh_soa, TAG_END());
......
......@@ -1992,7 +1992,13 @@ int nua_client_init_request(nua_client_request_t *cr)
url = (url_string_t const *)t->t_value;
}
t = nh->nh_tags, sip_add_tagis(msg, sip, &t);
t = nh->nh_tags;
/* Use the From header from the dialog */
if (ds->ds_leg && t->t_tag == siptag_from)
t++;
sip_add_tagis(msg, sip, &t);
}
if (!ds->ds_route) {
......
......@@ -222,6 +222,8 @@ struct nua_s {
/* Engine state flags */
unsigned nua_shutdown_started:1; /**< Shutdown initiated */
unsigned nua_shutdown_final:1; /**< Shutdown is complete */
unsigned nua_from_is_set;
unsigned :0;
/**< Used by stop-and-wait args calls */
......
......@@ -377,6 +377,7 @@ int test_prack_auth(struct context *ctx)
INVITE(c, c_call, c_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_FROM(c->to),
SOATAG_USER_SDP_STR(c_call->sdp),
TAG_END());
......@@ -420,6 +421,8 @@ int test_prack_auth(struct context *ctx)
}
TEST_E(e->data->e_event, nua_r_prack);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_from->a_url->url_user);
TEST_1(e = ei); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 200);
......
......@@ -74,6 +74,7 @@ int test_nua_init(struct context *ctx,
url_t const *p_uri, *a_uri, *b_uri; /* Proxy URI */
char const *initial_route = NULL; /* Initial route towards internal proxy */
char const *a_bind, *a_bind2;
url_t *e_proxy = NULL;
int err = -1;
url_t b_proxy[1];
......@@ -162,8 +163,13 @@ int test_nua_init(struct context *ctx,
p_uri = a_uri = b_uri = test_proxy_uri(ctx->p);
if (o_proxy) {
TEST_1(e_proxy = url_hdup(ctx->home, (void *)o_proxy));
ctx->external_proxy = e_proxy;
}
if (start_nat && p_uri == NULL)
p_uri = url_hdup(ctx->home, (void *)o_proxy);
p_uri = e_proxy;
if (ctx->p)
initial_route = test_proxy_route_uri(ctx->p, &ctx->lr);
......@@ -262,7 +268,7 @@ int test_nua_init(struct context *ctx,
ctx->a.instance = nua_generate_instance_identifier(ctx->home);
ctx->a.nua = nua_create(ctx->root, a_callback, ctx,
NUTAG_PROXY(a_uri ? a_uri : o_proxy),
NUTAG_PROXY(a_uri ? a_uri : e_proxy),
NUTAG_INITIAL_ROUTE_STR(initial_route),
SIPTAG_FROM_STR("sip:alice@example.com"),
NUTAG_URL(a_bind),
......@@ -310,7 +316,7 @@ int test_nua_init(struct context *ctx,
}
ctx->b.nua = nua_create(ctx->root, b_callback, ctx,
NUTAG_PROXY(b_uri ? b_uri : o_proxy),
NUTAG_PROXY(b_uri ? b_uri : e_proxy),
SIPTAG_FROM_STR("sip:bob@example.org"),
NUTAG_URL("sip:0.0.0.0:*"),
SOATAG_USER_SDP_STR("m=audio 5006 RTP/AVP 8 0"),
......@@ -350,9 +356,10 @@ int test_nua_init(struct context *ctx,
/* ctx->c.instance = nua_generate_instance_identifier(ctx->home); */
ctx->c.to = sip_from_make(ctx->home, "Charlie <sip:charlie@example.net>");
ctx->c.nua = nua_create(ctx->root, c_callback, ctx,
NUTAG_PROXY(p_uri ? p_uri : o_proxy),
SIPTAG_FROM_STR("sip:charlie@example.net"),
NUTAG_PROXY(p_uri ? p_uri : e_proxy),
NUTAG_URL("sip:0.0.0.0:*"),
SOATAG_USER_SDP_STR("m=audio 5400 RTP/AVP 8 0"),
NUTAG_INSTANCE(ctx->c.instance),
......@@ -365,15 +372,13 @@ int test_nua_init(struct context *ctx,
TEST_1(e = ctx->c.specials->head);
err = tl_gets(e->data->e_tags,
NTATAG_CONTACT_REF(m),
SIPTAG_FROM_REF(sipaddress),
SIPTAG_ALLOW_REF(allow),
NUTAG_APPL_METHOD_REF(appl_method),
SIPTAG_SUPPORTED_REF(supported),
TAG_END());
TEST(err, 5); TEST_1(m);
TEST(err, 4); TEST_1(m);
TEST_1(ctx->c.contact = sip_contact_dup(ctx->home, m));
TEST_1(ctx->c.to = sip_to_dup(ctx->home, sipaddress));
TEST_1(ctx->c.allow = sip_allow_dup(ctx->home, allow));
TEST_1(ctx->c.appl_method = su_strdup(ctx->home, appl_method));
TEST_1(ctx->c.supported = sip_supported_dup(ctx->home, supported));
......
......@@ -340,6 +340,8 @@ int main(int argc, char *argv[])
retval |= test_nua_destroy(ctx); SINGLE_FAILURE_CHECK();
retval |= test_stack_errors(ctx); SINGLE_FAILURE_CHECK();
retval |= test_nua_init(ctx, o_iproxy, o_proxy, o_inat,
TESTNATTAG_SYMMETRIC(o_inat_symmetric),
TESTNATTAG_LOGGING(o_inat_logging),
......@@ -354,8 +356,6 @@ int main(int argc, char *argv[])
if (o_events_c)
ctx->c.printer = print_event;
retval |= test_stack_errors(ctx); SINGLE_FAILURE_CHECK();
retval |= test_register(ctx);
if (retval == 0)
......
......@@ -126,7 +126,8 @@ struct context
int threading, proxy_tests, expensive, quit_on_single_failure, osx_runloop;
int print_tags;
char const *external_proxy;
url_t *external_proxy;
int proxy_logging;
......
......@@ -198,7 +198,7 @@ int test_nua_destroy(struct context *ctx)
/* ======================================================================== */
int test_stack_errors(struct context *ctx)
int test_byecancel_without_invite(struct context *ctx)
{
BEGIN();
......@@ -208,9 +208,6 @@ int test_stack_errors(struct context *ctx)
int internal_error = 900;
if (print_headings)
printf("TEST NUA-1.2: Stack error handling\n");
if (print_headings)
printf("TEST NUA-1.2.1: CANCEL without INVITE\n");
......@@ -252,8 +249,17 @@ int test_stack_errors(struct context *ctx)
if (print_headings)
printf("TEST NUA-1.2.2: PASSED\n");
if (!ctx->proxy_tests)
goto nua_1_2_5;
END();
}
int test_unregister_without_register(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call;
struct event *e;
/* -Un-register without REGISTER--------------------------------------- */
......@@ -301,10 +307,22 @@ int test_stack_errors(struct context *ctx)
if (print_headings)
printf("TEST NUA-1.2.4: PASSED\n");
END();
}
/* -terminate without notifier--------------------------------------- */
/* -terminate without notifier--------------------------------------- */
int test_terminate_without_notifier(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call;
struct event *e;
int internal_error = 900;
nua_1_2_5:
if (print_headings)
printf("TEST NUA-1.2.5: terminate without notifier\n");
......@@ -335,8 +353,108 @@ int test_stack_errors(struct context *ctx)
if (print_headings)
printf("TEST NUA-1.2.5: PASSED\n");
END();
}
int destroy_on_503(CONDITION_PARAMS)
{
save_event_in_list(ctx, event, ep, call);
if (status == 503) {
assert(nh == call->nh);
nua_handle_destroy(call->nh), call->nh = NULL;
}
return
nua_r_set_params <= event && event < nua_i_network_changed
&& status >= 200;
}
int test_register_503(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a;
struct call *a_reg = a->reg;
struct event *e;
/* REGISTER test
A
|------REGISTER--\
|<-------503-----/
|
*/
if (print_headings)
printf("TEST NUA-1.2.6: REGISTER with bad domain\n");
TEST_1(a_reg->nh = nua_handle(a->nua, a_reg, TAG_END()));
REGISTER(a, a_reg, a_reg->nh,
NUTAG_REGISTRAR(URL_STRING_MAKE("sip:bad.domain")),
SIPTAG_TO_STR("sip:lissu@bad.domain"),
TAG_END());
run_a_until(ctx, -1, destroy_on_503);
TEST_1(e = a->events->head);
TEST_E(e->data->e_event, nua_r_register);
TEST(e->data->e_status, 503);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
TEST_1(a_reg->nh = nua_handle(a->nua, a_reg, TAG_END()));
REGISTER(a, a_reg, a_reg->nh,
NUTAG_REGISTRAR(URL_STRING_MAKE("sip:bad.domain")),
SIPTAG_TO_STR("sip:lissu@bad.domain"),
TAG_END());
nua_handle_destroy(a_reg->nh), a_reg->nh = NULL;
if (print_headings)
printf("TEST NUA-1.2.6: PASSED\n");
END();
}
int test_stack_errors(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a;
if (print_headings)
printf("TEST NUA-1.2: Stack error handling\n");
TEST_1(ctx->root == NULL);
TEST_1(ctx->root = su_root_create(NULL));
a->nua = nua_create(ctx->root, a_callback, ctx,
NUTAG_URL("sip:0.0.0.0:*"),
TAG_IF(ctx->a.logging, TPTAG_LOG(1)),
TAG_END());
TEST_1(a->nua);
TEST(test_byecancel_without_invite(ctx), 0);
if (ctx->proxy_tests)
TEST(test_unregister_without_register(ctx), 0);
TEST(test_terminate_without_notifier(ctx), 0);
TEST(test_register_503(ctx), 0);
TEST(test_register_503(ctx), 0);
nua_shutdown(a->nua);
run_a_until(ctx, -1, until_final_response);
TEST_VOID(nua_destroy(a->nua));
su_root_destroy(ctx->root), ctx->root = NULL;
if (print_headings)
printf("TEST NUA-1.2: PASSED\n");
END();
}
......@@ -46,16 +46,30 @@
/* ======================================================================== */
/* Test REGISTER */
int test_clear_registrations(struct context *ctx);
int test_outbound_cases(struct context *ctx);
int test_register_a(struct context *ctx);
int test_register_b(struct context *ctx);
int test_register_c(struct context *ctx);
int test_register_refresh(struct context *ctx);
int test_register_to_proxy(struct context *ctx)
{
return
test_clear_registrations(ctx) ||
test_outbound_cases(ctx) ||
test_register_a(ctx) ||
test_register_b(ctx) ||
test_register_c(ctx) ||
test_register_refresh(ctx);
}
int test_clear_registrations(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c, *x;
struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c;
struct call *a_reg = a->reg, *b_reg = b->reg, *c_reg = c->reg;
struct event *e;
sip_t const *sip;
sip_cseq_t cseq[1];
int seen_401;
if (print_headings)
printf("TEST NUA-2.3.0.1: un-REGISTER a\n");
......@@ -93,7 +107,8 @@ int test_register_to_proxy(struct context *ctx)
printf("TEST NUA-2.3.0.3: un-REGISTER c\n");
TEST_1(c_reg->nh = nua_handle(c->nua, c_reg, TAG_END()));
UNREGISTER(c, c_reg, c_reg->nh, SIPTAG_TO(c->to),
UNREGISTER(c, c_reg, c_reg->nh,
SIPTAG_FROM(c->to), SIPTAG_TO(c->to),
SIPTAG_CONTACT_STR("*"),
TAG_END());
run_c_until(ctx, -1, until_final_response);
......@@ -105,9 +120,151 @@ int test_register_to_proxy(struct context *ctx)
if (print_headings)
printf("TEST NUA-2.3.0.3: PASSED\n");
END();
}
int test_outbound_cases(struct context *ctx)
{
BEGIN();
#if 0
struct endpoint *a = &ctx->a, *x;
struct call *a_reg = a->reg;
struct event *e;
sip_t const *sip;
sip_contact_t m[1];
/* REGISTER test
A B
A R
|------REGISTER----->|
|<-------401---------|
|------REGISTER----->|
|<-------200---------|
| |
*/
if (print_headings)
printf("TEST NUA-2.3.1: REGISTER a\n");
test_proxy_domain_set_expiration(ctx->a.domain, 5, 5, 10);
TEST_1(a_reg->nh = nua_handle(a->nua, a_reg, TAG_END()));
sip_contact_init(m);
m->m_display = "Lissu";
*m->m_url = *a->contact->m_url;
m->m_url->url_user = "a";
m->m_url->url_params = "transport=udp";
REGISTER(a, a_reg, a_reg->nh, SIPTAG_TO(a->to),
NUTAG_OUTBOUND("use-rport no-options-keepalive"),
SIPTAG_CONTACT(m),
TAG_END());
run_a_until(ctx, -1, save_until_final_response);
TEST_1(e = a->events->head);
TEST_E(e->data->e_event, nua_r_register);
TEST(e->data->e_status, 401);
TEST_1(sip = sip_object(e->data->e_msg));
TEST(sip->sip_status->st_status, 401);
TEST_1(!sip->sip_contact);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
AUTHENTICATE(a, a_reg, a_reg->nh,
NUTAG_AUTH("Digest:\"test-proxy\":alice:secret"), TAG_END());
run_a_until(ctx, -1, save_until_final_response);
TEST_1(e = a->events->head);
TEST_E(e->data->e_event, nua_r_register);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_contact);
TEST_S(sip->sip_contact->m_display, "Lissu");
TEST_S(sip->sip_contact->m_url->url_user, "a");
TEST_1(strstr(sip->sip_contact->m_url->url_params, "transport=udp"));
if (ctx->nat) {
TEST_1(e = a->specials->head);
}
test_proxy_domain_set_expiration(ctx->a.domain, 600, 3600, 36000);
if (print_headings)
printf("TEST NUA-2.3.1: PASSED\n");
if (print_headings)
printf("TEST NUA-2.3.4: refresh REGISTER\n");
if (!ctx->p) {
free_events_in_list(ctx, a->events);
return 0;
}
/* Wait for A to refresh its registrations */
/*
* Avoid race condition: if X has already refreshed registration
* with expiration time of 3600 seconds, do not wait for new refresh
*/
a->next_condition = save_until_final_response;
for (x = a; x; x = NULL) {
for (e = x->events->head; e; e = e->next) {
if (e->data->e_event == nua_r_register &&
e->data->e_status == 200 &&
(sip = sip_object(e->data->e_msg)) &&
sip->sip_contact &&
sip->sip_contact->m_expires &&
strcmp(sip->sip_contact->m_expires, "3600") == 0) {
x->next_condition = NULL;
break;
}
}
}
run_a_until(ctx, -1, a->next_condition);
for (e = a->events->head; e; e = e->next) {
TEST_E(e->data->e_event, nua_r_register);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_contact);
if (!e->next)
break;
}
TEST_1(e);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_S(sip->sip_contact->m_expires, "3600");
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
if (print_headings)
printf("TEST NUA-2.3.4: PASSED\n");
TEST_1(0);
#endif
END();
}
int test_register_a(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a;
struct call *a_reg = a->reg;
struct event *e;
sip_t const *sip;
sip_cseq_t cseq[1];
/* REGISTER test
A R
|------REGISTER----->|
|<-------401---------|
|------REGISTER----->|
......@@ -187,6 +344,18 @@ int test_register_to_proxy(struct context *ctx)
if (print_headings)
printf("TEST NUA-2.3.1: PASSED\n");
END();
}
int test_register_b(struct context *ctx)
{
BEGIN();
struct endpoint *b = &ctx->b;
struct call *b_reg = b->reg;
struct event *e;
sip_t const *sip;
if (print_headings)
printf("TEST NUA-2.3.2: REGISTER b\n");
......@@ -236,10 +405,22 @@ int test_register_to_proxy(struct context *ctx)
TEST_S(sip->sip_contact->m_url->url_user, "b");
free_events_in_list(ctx, b->events);
test_proxy_domain_set_expiration(ctx->b.domain, 600, 3600, 36000);
if (print_headings)
printf("TEST NUA-2.3.2: PASSED\n");
test_proxy_domain_set_expiration(ctx->b.domain, 600, 3600, 36000);
END();
}
int test_register_c(struct context *ctx)
{
BEGIN();
struct endpoint *c = &ctx->c;
struct call *c_reg = c->reg;
struct event *e;
sip_t const *sip;
if (print_headings)
printf("TEST NUA-2.3.3: REGISTER c\n");
......@@ -249,7 +430,8 @@ int test_register_to_proxy(struct context *ctx)
TEST_1(c_reg->nh = nua_handle(c->nua, c_reg, TAG_END()));
REGISTER(c, c_reg, c_reg->nh, SIPTAG_TO(c->to),
REGISTER(c, c_reg, c_reg->nh, SIPTAG_TO(c->to),
SIPTAG_FROM(c->to),
NUTAG_OUTBOUND(NULL),
NUTAG_M_DISPLAY("C"),
NUTAG_M_USERNAME("c"),
......@@ -300,15 +482,27 @@ int test_register_to_proxy(struct context *ctx)
if (print_headings)
printf("TEST NUA-2.3.3: PASSED\n");
END();
}
int test_register_refresh(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b, *x;
struct event *e;
sip_t const *sip;
int seen_401;
if (print_headings)
printf("TEST NUA-2.3.4: refresh REGISTER\n");
if (!ctx->p) {
free_events_in_list(ctx, a->events);
free_events_in_list(ctx, b->events);
return 0;
}
if (print_headings)
printf("TEST NUA-2.3.4: refresh REGISTER\n");
/* Wait for A and B to refresh their registrations */
/*
......@@ -343,6 +537,7 @@ int test_register_to_proxy(struct context *ctx)
break;
}
TEST_1(e);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_S(sip->sip_contact->m_expires, "3600");
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
......@@ -569,6 +764,7 @@ int test_connectivity(struct context *ctx)
TEST_1(c_call->nh = nua_handle(c->nua, c_call, SIPTAG_TO(a->to), TAG_END()));
OPTIONS(c, c_call, c_call->nh,
SIPTAG_FROM(c->to),
TAG_IF(!ctx->proxy_tests, NUTAG_URL(a->contact->m_url)),
TAG_END());
......@@ -767,7 +963,7 @@ int test_unregister(struct context *ctx)
/* Unregister using another handle */
free_events_in_list(ctx, c->events);
TEST_1(c->call->nh = nua_handle(c->nua, c->call, TAG_END()));
UNREGISTER(c, c->call, c->call->nh, SIPTAG_TO(c->to),
UNREGISTER(c, c->call, c->call->nh, SIPTAG_TO(c->to), SIPTAG_FROM(c->to),
NUTAG_M_DISPLAY("C"),
NUTAG_M_USERNAME("c"),
NUTAG_M_PARAMS("c=1"),
......@@ -807,6 +1003,7 @@ int test_unregister(struct context *ctx)
}
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_from->a_url->url_user);
TEST_1(!sip->sip_contact);
TEST_1(!e->next);
free_events_in_list(ctx, c->events);
......
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