Commit 7b3750f2 authored by Pekka Pessi's avatar Pekka Pessi

nua_session.c: updated session timer implementation.

The session timers are defined in RFC 4028. The update involves use of
"timer" feature tag: if it is not given by UAC, assume UAS always refreshes.

Updated test_nua.c and test_proxy.c, too.

darcs-hash:20060728093527-65a35-175ec28ca29b3fc9d1a489316d7329366bda4dc4.gz
parent 04187b7e
......@@ -1449,7 +1449,7 @@ int process_timeout(nua_handle_t *nh,
/* ---------------------------------------------------------------------- */
/* Session timer */
/* Session timer - RFC 4028 */
/** Add timer featuretag and Session-Expires/Min-SE headers */
static int
......@@ -1499,14 +1499,17 @@ init_session_timer(nua_handle_t *nh, sip_t const *sip)
int server;
ss->ss_refresher = nua_no_refresher;
/* Session timer is not needed */
if (!sip->sip_session_expires)
return 0;
/* Check if we support the timer feature */
if (!sip->sip_session_expires ||
!sip_has_supported(NH_PGET(nh, supported), "timer")) {
if (!sip_has_supported(NH_PGET(nh, supported), "timer")) {
return 0;
}
ss->ss_refresher = nua_no_refresher;
ss->ss_session_timer = sip->sip_session_expires->x_delta;
if (sip->sip_min_se != NULL
......@@ -1515,7 +1518,9 @@ init_session_timer(nua_handle_t *nh, sip_t const *sip)
server = sip->sip_request != NULL;
if (!str0casecmp("uac", sip->sip_session_expires->x_refresher))
if (!sip_has_supported(sip->sip_supported, "timer"))
ss->ss_refresher = nua_local_refresher;
else if (!str0casecmp("uac", sip->sip_session_expires->x_refresher))
ss->ss_refresher = server ? nua_remote_refresher : nua_local_refresher;
else if (!str0casecmp("uas", sip->sip_session_expires->x_refresher))
ss->ss_refresher = server ? nua_local_refresher : nua_remote_refresher;
......@@ -1527,6 +1532,12 @@ init_session_timer(nua_handle_t *nh, sip_t const *sip)
else
ss->ss_refresher = nua_remote_refresher;
SU_DEBUG_9(("nua(%p): session expires in %u refreshed by %s (%s %s)\n",
nh, ss->ss_session_timer,
ss->ss_refresher == nua_local_refresher ? "local" : "remote",
server ? sip->sip_request->rq_method_name : "response to",
server ? "request" : sip->sip_cseq->cs_method_name));
return 0;
}
......
......@@ -4193,7 +4193,11 @@ int test_session_timer(struct context *ctx)
/* Session timer test:
A B
A P B
|--INVITE->| |
|<--422----| |
|---ACK--->| |
| |
|-------INVITE------>|
|<-------422---------|
|--------ACK-------->|
......@@ -4229,6 +4233,9 @@ int test_session_timer(struct context *ctx)
/* Client transitions:
INIT -(C1)-> CALLING: nua_invite(), nua_i_state
CALLING -(C6a)-> (TERMINATED/INIT): nua_r_invite
when testing with proxy, second 422 when call reaches UAS:
(INIT) -(C1)-> CALLING: nua_i_state
CALLING -(C6a)-> (TERMINATED/INIT): nua_r_invite
(INIT) -(C1)-> CALLING: nua_i_state
CALLING -(C2)-> PROCEEDING: nua_r_invite, nua_i_state
PROCEEDING -(C3+C4)-> READY: nua_r_invite, nua_i_state
......@@ -4239,6 +4246,16 @@ int test_session_timer(struct context *ctx)
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, 422);
if (ctx->proxy_tests) {
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, 100);
TEST(sip_object(e->data->e_msg)->sip_status->st_status, 422);
}
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));
......@@ -5044,7 +5061,7 @@ int test_100rel(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;
if (print_headings)
printf("TEST NUA-10.1: Call with 100rel and 180\n");
......@@ -5361,7 +5378,7 @@ int test_100rel(struct context *ctx)
nua_set_params(ctx->b.nua,
NUTAG_EARLY_MEDIA(0),
SIPTAG_SUPPORTED_STR("100rel, precondition"),
SIPTAG_SUPPORTED_STR("100rel, precondition, timer"),
TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
......@@ -5426,6 +5443,10 @@ int test_100rel(struct context *ctx)
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_session_expires);
TEST_S(sip->sip_session_expires->x_refresher, "uas");
TEST_1(!sip_has_supported(sip->sip_require, "timer"));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
......
......@@ -108,6 +108,8 @@ struct proxy {
struct {
sip_time_t min_expires, expires, max_expires;
sip_time_t session_expires, min_se;
} prefs;
};
......@@ -261,6 +263,9 @@ test_proxy_init(su_root_t *root, struct proxy *proxy)
proxy->prefs.expires = 3600;
proxy->prefs.max_expires = 3600;
proxy->prefs.session_expires = 180;
proxy->prefs.min_se = 90;
if (!proxy->defleg ||
!proxy->example_net || !proxy->example_org || !proxy->example_com)
return -1;
......@@ -418,6 +423,9 @@ int proxy_request(struct proxy *proxy,
sip_max_forwards_t *mf;
sip_method_t method = sip->sip_request->rq_method;
sip_session_expires_t *x = NULL, x0[1];
sip_min_se_t *min_se = NULL, min_se0[1];
mf = sip->sip_max_forwards;
if (mf && mf->mf_count <= 1) {
......@@ -436,6 +444,28 @@ int proxy_request(struct proxy *proxy,
return status;
}
if (method == sip_method_invite) {
if (!sip->sip_min_se ||
sip->sip_min_se->min_delta < proxy->prefs.min_se) {
min_se = sip_min_se_init(min_se0);
min_se->min_delta = proxy->prefs.min_se;
}
if (!sip->sip_session_expires) {
x = sip_session_expires_init(x0);
x->x_delta = proxy->prefs.session_expires;
}
else if (sip->sip_session_expires->x_delta < proxy->prefs.min_se
&& sip_has_supported(sip->sip_supported, "timer")) {
if (min_se == NULL)
min_se = sip->sip_min_se; assert(min_se);
nta_incoming_treply(irq, SIP_422_SESSION_TIMER_TOO_SMALL,
SIPTAG_MIN_SE(min_se),
TAG_END());
return 422;
}
}
/* We don't do any route processing */
request_uri = sip->sip_request->rq_url;
......@@ -494,6 +524,8 @@ int proxy_request(struct proxy *proxy,
nta_incoming_getrequest(irq),
/* rewrite request */
SIPTAG_REQUEST(rq),
SIPTAG_SESSION_EXPIRES(x),
SIPTAG_MIN_SE(min_se),
TAG_END());
if (t->client == NULL) {
proxy_transaction_destroy(t);
......
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