Commit 8161d3da authored by Pekka Pessi's avatar Pekka Pessi
Browse files

nua_register.c: re-registering in case the TCP connection towards proxy is closed

In test_nua, Mr. B is now using TCP with the test proxy.

darcs-hash:20070601192755-65a35-4c2e341a25335fafbc7a36059c1fc4766f2093e9.gz
parent 2d4cfda0
......@@ -37,6 +37,8 @@
/** @internal SU network changed detector argument pointer type */
#define SU_NETWORK_CHANGED_MAGIC_T struct nua_s
#define TP_CLIENT_T struct register_usage
#include <sofia-sip/string0.h>
#include <sofia-sip/su_strlst.h>
#include <sofia-sip/su_uniqueid.h>
......@@ -46,7 +48,7 @@
#include <sofia-sip/sip_util.h>
#include <sofia-sip/sip_status.h>
#define NTA_UPDATE_MAGIC_T struct nua_s
#define NTA_UPDATE_MAGIC_T struct nua_handle_s
#include "nua_stack.h"
......@@ -126,6 +128,7 @@ struct register_usage {
/** Status of registration */
unsigned nr_ready:1;
/** Kind of registration.
*
* If nr_default is true, this is not a real registration but placeholder
......@@ -138,7 +141,11 @@ struct register_usage {
unsigned nr_default:1, nr_secure:1, nr_public:1, nr_ip4:1, nr_ip6:1;
/** Stack-generated contact */
unsigned nr_by_stack:1, :0;
unsigned nr_by_stack:1;
unsigned:0;
int nr_error_report_id; /**< ID used to ask for error reports from tport */
sip_route_t *nr_route; /**< Outgoing Service-Route */
sip_path_t *nr_path; /**< Incoming Path */
......@@ -205,6 +212,12 @@ static void nua_register_usage_remove(nua_handle_t *nh,
nr->nr_compartment = NULL;
#endif
if (nr->nr_error_report_id)
tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0);
if (nr->nr_tport)
tport_unref(nr->nr_tport), nr->nr_tport = NULL;
ds->ds_has_register = 0; /* There can be only one */
}
......@@ -222,6 +235,12 @@ static void nua_register_usage_peer_info(nua_dialog_usage_t *du,
/* ======================================================================== */
/* REGISTER */
static void nua_register_connection_closed(tp_stack_t *sip_stack,
nua_registration_t *nr,
tport_t *tport,
msg_t *msg,
int error);
/* Interface towards outbound_t */
sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
su_home_t *home,
......@@ -764,6 +783,7 @@ int nua_register_client_request(nua_client_request_t *cr,
TAG_IF(unreg, NTATAG_SIGCOMP_CLOSE(1)),
TAG_IF(!unreg, NTATAG_COMP("sigcomp")),
#endif
NTATAG_TPORT(nr->nr_tport),
TAG_NEXT(tags));
}
......@@ -827,6 +847,8 @@ static int nua_register_client_response(nua_client_request_t *cr,
msg_t *_reqmsg = nta_outgoing_getrequest(cr->cr_orq);
sip_t *req = sip_object(_reqmsg);
tport_t *tport;
msg_destroy(_reqmsg);
assert(nr); assert(sip); assert(req);
......@@ -927,10 +949,26 @@ static int nua_register_client_response(nua_client_request_t *cr,
outbound_start_keepalive(nr->nr_ob, cr->cr_orq);
}
/* persistant connection for registration */
if (!nr->nr_tport)
/* note: nta_outgoing_transport() takes a ref */
nr->nr_tport = nta_outgoing_transport (cr->cr_orq);
tport = nta_outgoing_transport (cr->cr_orq);
/* cache persistant connection for registration */
if (tport && tport != nr->nr_tport) {
if (nr->nr_error_report_id) {
if (tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0) < 0)
SU_DEBUG_1(("nua_register: tport_release() failed\n"));
nr->nr_error_report_id = 0;
}
tport_unref(nr->nr_tport);
nr->nr_tport = tport;
if (tport_is_secondary(tport)) {
tport_set_params(tport, TPTAG_SDWN_ERROR(1), TAG_END());
nr->nr_error_report_id =
tport_pend(tport, NULL, nua_register_connection_closed, nr);
}
}
else
tport_unref(tport); /* note: nta_outgoing_transport() makes a ref */
nua_registration_set_ready(nr, 1);
}
......@@ -943,9 +981,15 @@ static int nua_register_client_response(nua_client_request_t *cr,
outbound_stop_keepalive(nr->nr_ob);
/* release the persistant transport for registration */
if (nr->nr_tport)
tport_decref(&nr->nr_tport), nr->nr_tport = NULL;
if (nr->nr_tport) {
if (nr->nr_error_report_id) {
if (tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0) < 0)
SU_DEBUG_1(("nua_register: tport_release() failed\n"));
nr->nr_error_report_id = 0;
}
tport_unref(nr->nr_tport), nr->nr_tport = NULL;
}
nua_registration_set_ready(nr, 0);
}
......@@ -953,6 +997,24 @@ static int nua_register_client_response(nua_client_request_t *cr,
return nua_base_client_response(cr, status, phrase, sip, NULL);
}
static
void nua_register_connection_closed(tp_stack_t *sip_stack,
nua_registration_t *nr,
tport_t *tport,
msg_t *msg,
int error)
{
if (tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0) < 0)
SU_DEBUG_1(("nua_register: tport_release() failed\n"));
nr->nr_error_report_id = 0;
tport_unref(nr->nr_tport), nr->nr_tport = NULL;
/* Schedule re-REGISTER immediately */
nua_dialog_usage_refresh_at(nua_dialog_usage_public(nr), sip_now());
}
static void nua_register_usage_refresh(nua_handle_t *nh,
nua_dialog_state_t *ds,
nua_dialog_usage_t *du,
......@@ -978,8 +1040,8 @@ static void nua_register_usage_refresh(nua_handle_t *nh,
* @retval <0 try again later
*/
static int nua_register_usage_shutdown(nua_handle_t *nh,
nua_dialog_state_t *ds,
nua_dialog_usage_t *du)
nua_dialog_state_t *ds,
nua_dialog_usage_t *du)
{
nua_client_request_t *cr = du->du_cr;
nua_registration_t *nr = nua_dialog_usage_private(du);
......
......@@ -1349,11 +1349,14 @@ int test_bye_to_invalid_contact(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 *sip = NULL;
int seen_401;
a_call->sdp = "m=audio 5008 RTP/AVP 8";
b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
/* Early BYE 2
/* Bad Contact URI
A B
|-------INVITE------>|
......@@ -1362,14 +1365,17 @@ int test_bye_to_invalid_contact(struct context *ctx)
|<----180 Ringing----|
|<-------200---------|
| |
|--------BYE-------->|
|<------200 OK-------|
|--------ACK-------->|
| |
|<-------BYE---------|
|--------400-------->|
| |
|--------BYE-------->|
|<------200 OK-------|
| |
*/
if (print_headings)
printf("TEST NUA-6.4.3: BYE call when completing\n");
printf("TEST NUA-6.4.3: Test dialog with bad Contact info\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
......@@ -1448,6 +1454,42 @@ int test_bye_to_invalid_contact(struct context *ctx)
if (print_headings)
printf("TEST NUA-6.4.3: PASSED\n");
if (!ctx->p)
return 0;
if (print_headings)
printf("TEST NUA-6.4.4: Wait for re-REGISTER after connection has been closed\n");
/* B is supposed to re-register pretty soon, wait for re-registration */
run_b_until(ctx, -1, save_until_final_response);
seen_401 = 0;
for (e = b->events->head; e; e = e->next) {
TEST_E(e->data->e_event, nua_r_register);
TEST_1(sip = sip_object(e->data->e_msg));
if (e->data->e_status == 200) {
TEST(e->data->e_status, 200);
TEST_1(seen_401);
TEST_1(sip->sip_contact);
}
else if (sip->sip_status && sip->sip_status->st_status == 401) {
seen_401 = 1;
}
if (!e->next)
break;
}
TEST_1(e);
TEST_S(sip->sip_contact->m_expires, "3600");
TEST_1(!e->next);
free_events_in_list(ctx, b->events);
if (print_headings)
printf("TEST NUA-6.4.4: PASSED\n");
END();
}
......
......@@ -70,8 +70,9 @@ int test_nua_init(struct context *ctx,
sip_allow_t const *allow = NULL;
sip_supported_t const *supported = NULL;
char const *appl_method = NULL;
url_t const *p_uri, *a_uri; /* Proxy URI */
url_t const *p_uri, *a_uri, *b_uri; /* Proxy URI */
char const *a_bind, *a_bind2;
url_t b_proxy[1];
a_bind = a_bind2 = "sip:0.0.0.0:*";
......@@ -121,7 +122,7 @@ int test_nua_init(struct context *ctx,
printf("TEST NUA-2.1.1: PASSED\n");
}
p_uri = a_uri = test_proxy_uri(ctx->p);
p_uri = a_uri = b_uri = test_proxy_uri(ctx->p);
if (start_nat && p_uri == NULL)
p_uri = url_hdup(ctx->home, (void *)o_proxy);
......@@ -257,8 +258,15 @@ int test_nua_init(struct context *ctx,
ctx->b.instance = nua_generate_instance_identifier(ctx->home);
if (ctx->p) {
/* B uses TCP when talking with proxy */
*b_proxy = *b_uri;
b_uri = b_proxy;
b_proxy->url_params = "transport=tcp";
}
ctx->b.nua = nua_create(ctx->root, b_callback, ctx,
NUTAG_PROXY(p_uri ? p_uri : o_proxy),
NUTAG_PROXY(b_uri ? b_uri : o_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"),
......
......@@ -200,6 +200,10 @@ int test_register_to_proxy(struct context *ctx)
m->m_display = "B";
m->m_url->url_user = "b";
/* Include "tcp" transport parameter in Contact */
if (ctx->p)
m->m_url->url_params = "transport=tcp";
REGISTER(b, b_reg, b_reg->nh, SIPTAG_TO(b->to),
SIPTAG_CONTACT(m),
/* Do not include credentials unless challenged */
......@@ -229,11 +233,14 @@ int test_register_to_proxy(struct context *ctx)
TEST_S(sip->sip_contact->m_display, "B");
TEST_S(sip->sip_contact->m_url->url_user, "b");
free_events_in_list(ctx, b->events);
if (print_headings)
printf("TEST NUA-2.3.2: PASSED\n");
if (ctx->p)
if (ctx->p) {
test_proxy_close_tports(ctx->p);
test_proxy_set_expiration(ctx->p, 600, 3600, 36000);
}
if (print_headings)
printf("TEST NUA-2.3.3: REGISTER c\n");
......
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