mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-13 12:40:17 +00:00
Thu Apr 24 11:31:48 EDT 2008 first.last@nokia.com
* nua: fixed problems with event fetch With event fetch the subscription was terminated before the NOTIFY was sent/received or final response to SUBSCRIBE was sent. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8285 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
fb34d3835c
commit
c497958ce9
@ -558,9 +558,6 @@ static int nua_notify_client_init(nua_client_request_t *cr,
|
||||
}
|
||||
}
|
||||
|
||||
if (nu->nu_substate == nua_substate_terminated)
|
||||
cr->cr_terminating = 1;
|
||||
|
||||
cr->cr_usage = du;
|
||||
|
||||
return nua_notify_client_init_etag(cr, msg, sip, tags);
|
||||
@ -700,6 +697,18 @@ int nua_notify_client_request(nua_client_request_t *cr,
|
||||
if (nu->nu_substate == nua_substate_terminated)
|
||||
cr->cr_terminating = 1;
|
||||
|
||||
if (cr->cr_terminating) {
|
||||
nua_server_request_t *sr;
|
||||
for (sr = du->du_dialog->ds_sr; sr; sr = sr->sr_next) {
|
||||
if (sr->sr_usage == du) {
|
||||
/* If subscribe has not been responded, don't terminate usage by NOTIFY */
|
||||
sr->sr_terminating = 1;
|
||||
cr->cr_terminating = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (du->du_event && !sip->sip_event)
|
||||
sip_add_dup(cr->cr_msg, sip, (sip_header_t *)du->du_event);
|
||||
|
||||
|
@ -248,15 +248,18 @@ static int nua_subscribe_client_request(nua_client_request_t *cr,
|
||||
nua_dialog_usage_t *du = cr->cr_usage;
|
||||
sip_time_t expires = 0;
|
||||
|
||||
if (cr->cr_event != nua_r_subscribe ||
|
||||
(du && du->du_shutdown) ||
|
||||
(sip->sip_expires && sip->sip_expires->ex_delta == 0))
|
||||
if (cr->cr_event != nua_r_subscribe || !du || du->du_shutdown)
|
||||
cr->cr_terminating = 1;
|
||||
|
||||
if (du) {
|
||||
struct event_usage *eu = nua_dialog_usage_private(du);
|
||||
sip_event_t *o = sip->sip_event;
|
||||
|
||||
if (eu->eu_notified &&
|
||||
sip->sip_expires &&
|
||||
sip->sip_expires->ex_delta == 0)
|
||||
cr->cr_terminating = 1;
|
||||
|
||||
if (nua_client_bind(cr, du) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -607,6 +607,27 @@ int accept_and_notify_twice(CONDITION_PARAMS)
|
||||
}
|
||||
}
|
||||
|
||||
int save_until_responded_and_notified_twice(CONDITION_PARAMS)
|
||||
{
|
||||
save_event_in_list(ctx, event, ep, call);
|
||||
|
||||
if (event == nua_i_notify) {
|
||||
if (ep->flags.bit0)
|
||||
ep->flags.bit1 = 1;
|
||||
ep->flags.bit0 = 1;
|
||||
}
|
||||
|
||||
if (event == nua_r_subscribe || event == nua_r_unsubscribe) {
|
||||
if (status >= 300)
|
||||
return 1;
|
||||
else if (status >= 200) {
|
||||
ep->flags.bit2 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ep->flags.bit0 && ep->flags.bit1 && ep->flags.bit2;
|
||||
}
|
||||
|
||||
|
||||
int accept_and_notify(CONDITION_PARAMS)
|
||||
{
|
||||
@ -620,16 +641,21 @@ int accept_and_notify(CONDITION_PARAMS)
|
||||
switch (event) {
|
||||
case nua_i_subscribe:
|
||||
if (status < 200) {
|
||||
int fetch = sip->sip_expires && sip->sip_expires->ex_delta == 0;
|
||||
|
||||
RESPOND(ep, call, nh, SIP_202_ACCEPTED,
|
||||
NUTAG_WITH(with),
|
||||
SIPTAG_EXPIRES_STR("360"),
|
||||
SIPTAG_EXPIRES(sip->sip_expires),
|
||||
TAG_END());
|
||||
|
||||
NOTIFY(ep, call, nh,
|
||||
SIPTAG_EVENT(sip->sip_event),
|
||||
SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"),
|
||||
SIPTAG_PAYLOAD_STR(presence_closed),
|
||||
NUTAG_SUBSTATE(nua_substate_pending),
|
||||
NUTAG_SUBSTATE(fetch
|
||||
? nua_substate_pending
|
||||
: nua_substate_terminated),
|
||||
TAG_END());
|
||||
|
||||
}
|
||||
@ -695,7 +721,7 @@ int test_subscribe_notify(struct context *ctx)
|
||||
SIPTAG_ACCEPT_STR("application/xpidf, application/pidf+xml"),
|
||||
TAG_END());
|
||||
|
||||
run_ab_until(ctx, -1, save_until_notified_and_responded,
|
||||
run_ab_until(ctx, -1, save_until_responded_and_notified_twice,
|
||||
-1, accept_and_notify_twice);
|
||||
|
||||
/* Client events:
|
||||
@ -727,10 +753,16 @@ int test_subscribe_notify(struct context *ctx)
|
||||
TEST_1(e = es); TEST_E(e->data->e_event, nua_r_subscribe);
|
||||
TEST_1(e->data->e_status == 202 || e->data->e_status == 200);
|
||||
TEST_1(tl_find(e->data->e_tags, nutag_substate));
|
||||
if (es == a->events->head)
|
||||
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_embryonic);
|
||||
else
|
||||
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_pending);
|
||||
r_tags = tl_find(e->data->e_tags, nutag_substate);
|
||||
if (es == a->events->head) {
|
||||
TEST(r_tags->t_value, nua_substate_embryonic);
|
||||
}
|
||||
else if (es == a->events->head->next) {
|
||||
TEST_1(r_tags->t_value == nua_substate_pending);
|
||||
}
|
||||
else {
|
||||
TEST_1(r_tags->t_value == nua_substate_active);
|
||||
}
|
||||
TEST_1(sip = sip_object(e->data->e_msg));
|
||||
TEST_1(sip->sip_expires);
|
||||
TEST_1(sip->sip_expires->ex_delta <= 333);
|
||||
@ -1164,6 +1196,235 @@ int save_until_notify_responded_twice(CONDITION_PARAMS)
|
||||
return ep->flags.bit0 && ep->flags.bit1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* When incoming SUBSCRIBE, send NOTIFY,
|
||||
* 200 OK SUBSCRIBE when NOTIFY has been responded.
|
||||
*/
|
||||
int notify_and_accept(CONDITION_PARAMS)
|
||||
{
|
||||
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
|
||||
return 0;
|
||||
|
||||
save_event_in_list(ctx, event, ep, call);
|
||||
|
||||
switch (event) {
|
||||
case nua_i_subscribe:
|
||||
if (status < 200) {
|
||||
NOTIFY(ep, call, nh,
|
||||
SIPTAG_EVENT(sip->sip_event),
|
||||
SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"),
|
||||
SIPTAG_PAYLOAD_STR(presence_closed),
|
||||
TAG_END());
|
||||
}
|
||||
return 0;
|
||||
|
||||
case nua_r_notify:
|
||||
if (status >= 200) {
|
||||
struct event *e;
|
||||
for (e = ep->events->head; e; e = e->next) {
|
||||
if (e->data->e_event == nua_i_subscribe) {
|
||||
RESPOND(ep, call, nh, SIP_200_OK,
|
||||
NUTAG_WITH(e->data->e_msg),
|
||||
TAG_END());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int test_event_fetch(struct context *ctx)
|
||||
{
|
||||
BEGIN();
|
||||
|
||||
struct endpoint *a = &ctx->a, *b = &ctx->b;
|
||||
struct call *a_call = a->call, *b_call = b->call;
|
||||
struct event *e, *en1, *en2, *es;
|
||||
sip_t const *sip;
|
||||
tagi_t const *r_tags;
|
||||
|
||||
if (print_headings)
|
||||
printf("TEST NUA-11.6.1: event fetch using nua_notify()\n");
|
||||
|
||||
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
|
||||
|
||||
/* Fetch 1:
|
||||
|
||||
A B
|
||||
| |
|
||||
|------SUBSCRIBE----->|
|
||||
| Expires: 0 |
|
||||
|<---------202--------|
|
||||
| |
|
||||
|<-------NOTIFY-------|
|
||||
| S-State: terminated |
|
||||
|-------200 OK------->|
|
||||
| |
|
||||
*/
|
||||
|
||||
SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url),
|
||||
SIPTAG_EVENT_STR("presence"),
|
||||
SIPTAG_EXPIRES_STR("0"),
|
||||
SIPTAG_ACCEPT_STR("application/xpidf, application/pidf+xml"),
|
||||
TAG_END());
|
||||
|
||||
run_ab_until(ctx, -1, save_until_notified_and_responded,
|
||||
-1, accept_and_notify);
|
||||
|
||||
/* Client events:
|
||||
nua_subscribe(), nua_i_notify/nua_r_subscribe/nua_i_notify
|
||||
*/
|
||||
for (en1 = en2 = es = NULL, e = a->events->head; e; e = e->next) {
|
||||
if (en1 == NULL && e->data->e_event == nua_i_notify)
|
||||
en1 = e;
|
||||
else if (en2 == NULL && e->data->e_event == nua_i_notify)
|
||||
en2 = e;
|
||||
else if (e->data->e_event == nua_r_subscribe)
|
||||
es = e;
|
||||
else
|
||||
TEST_1(!e);
|
||||
}
|
||||
|
||||
TEST_1(e = en1);
|
||||
TEST_E(e->data->e_event, nua_i_notify);
|
||||
TEST_1(tl_find(e->data->e_tags, nutag_substate));
|
||||
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_terminated);
|
||||
TEST_1(sip = sip_object(e->data->e_msg));
|
||||
TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence");
|
||||
TEST_1(sip->sip_content_type);
|
||||
TEST_S(sip->sip_content_type->c_type, "application/pidf+xml");
|
||||
TEST_1(sip->sip_subscription_state);
|
||||
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
|
||||
|
||||
TEST_1(e = es); TEST_E(e->data->e_event, nua_r_subscribe);
|
||||
TEST_1(e->data->e_status == 202 || e->data->e_status == 200);
|
||||
TEST_1(tl_find(e->data->e_tags, nutag_substate));
|
||||
|
||||
if (es == a->events->head)
|
||||
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_embryonic);
|
||||
else
|
||||
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_terminated);
|
||||
TEST_1(sip = sip_object(e->data->e_msg));
|
||||
TEST_1(sip->sip_expires);
|
||||
TEST_1(sip->sip_expires->ex_delta == 0);
|
||||
|
||||
free_events_in_list(ctx, a->events);
|
||||
|
||||
/* Server events: nua_i_subscribe, nua_r_notify */
|
||||
TEST_1(e = b->events->head);
|
||||
TEST_E(e->data->e_event, nua_i_subscribe);
|
||||
TEST_E(e->data->e_status, 100);
|
||||
TEST_1(sip = sip_object(e->data->e_msg));
|
||||
|
||||
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
|
||||
r_tags = e->data->e_tags;
|
||||
TEST_1(tl_find(r_tags, nutag_substate));
|
||||
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
|
||||
|
||||
free_events_in_list(ctx, b->events);
|
||||
|
||||
if (print_headings)
|
||||
printf("TEST NUA-11.6.1: PASSED\n");
|
||||
|
||||
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
|
||||
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
|
||||
|
||||
|
||||
if (print_headings)
|
||||
printf("TEST NUA-11.6.2: event fetch, NOTIFY comes before 202\n");
|
||||
|
||||
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
|
||||
|
||||
/* Fetch 2:
|
||||
|
||||
A B
|
||||
| |
|
||||
|------SUBSCRIBE----->|
|
||||
| Expires: 0 |
|
||||
|<-------NOTIFY-------|
|
||||
| S-State: terminated |
|
||||
|-------200 OK------->|
|
||||
| |
|
||||
|<---------202--------|
|
||||
| |
|
||||
*/
|
||||
|
||||
SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url),
|
||||
SIPTAG_EVENT_STR("presence"),
|
||||
SIPTAG_EXPIRES_STR("0"),
|
||||
SIPTAG_ACCEPT_STR("application/xpidf, application/pidf+xml"),
|
||||
TAG_END());
|
||||
|
||||
run_ab_until(ctx, -1, save_until_notified_and_responded,
|
||||
-1, notify_and_accept);
|
||||
|
||||
/* Client events:
|
||||
nua_subscribe(), nua_i_notify/nua_r_subscribe/nua_i_notify
|
||||
*/
|
||||
for (en1 = en2 = es = NULL, e = a->events->head; e; e = e->next) {
|
||||
if (en1 == NULL && e->data->e_event == nua_i_notify)
|
||||
en1 = e;
|
||||
else if (en2 == NULL && e->data->e_event == nua_i_notify)
|
||||
en2 = e;
|
||||
else if (e->data->e_event == nua_r_subscribe)
|
||||
es = e;
|
||||
else
|
||||
TEST_1(!e);
|
||||
}
|
||||
|
||||
TEST_1(e = en1);
|
||||
TEST_E(e->data->e_event, nua_i_notify);
|
||||
TEST_1(tl_find(e->data->e_tags, nutag_substate));
|
||||
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_terminated);
|
||||
TEST_1(sip = sip_object(e->data->e_msg));
|
||||
TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence");
|
||||
TEST_1(sip->sip_content_type);
|
||||
TEST_S(sip->sip_content_type->c_type, "application/pidf+xml");
|
||||
TEST_1(sip->sip_subscription_state);
|
||||
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
|
||||
|
||||
TEST_1(e = es); TEST_E(e->data->e_event, nua_r_subscribe);
|
||||
TEST_1(e->data->e_status == 202 || e->data->e_status == 200);
|
||||
TEST_1(tl_find(e->data->e_tags, nutag_substate));
|
||||
|
||||
if (es == a->events->head)
|
||||
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_embryonic);
|
||||
else
|
||||
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_terminated);
|
||||
TEST_1(sip = sip_object(e->data->e_msg));
|
||||
TEST_1(sip->sip_expires);
|
||||
TEST_1(sip->sip_expires->ex_delta == 0);
|
||||
|
||||
free_events_in_list(ctx, a->events);
|
||||
|
||||
/* Server events: nua_i_subscribe, nua_r_notify */
|
||||
TEST_1(e = b->events->head);
|
||||
TEST_E(e->data->e_event, nua_i_subscribe);
|
||||
TEST_E(e->data->e_status, 100);
|
||||
TEST_1(sip = sip_object(e->data->e_msg));
|
||||
|
||||
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
|
||||
r_tags = e->data->e_tags;
|
||||
TEST_1(tl_find(r_tags, nutag_substate));
|
||||
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
|
||||
|
||||
free_events_in_list(ctx, b->events);
|
||||
|
||||
if (print_headings)
|
||||
printf("TEST NUA-11.6.2: PASSED\n");
|
||||
|
||||
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
|
||||
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
|
||||
|
||||
END();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Unsolicited NOTIFY */
|
||||
|
||||
@ -1830,6 +2091,7 @@ int test_simple(struct context *ctx)
|
||||
|| test_message(ctx)
|
||||
|| test_publish(ctx)
|
||||
|| test_subscribe_notify(ctx)
|
||||
|| test_event_fetch(ctx)
|
||||
|| test_subscribe_notify_graceful(ctx)
|
||||
|| test_newsub_notify(ctx)
|
||||
|| test_subscription_timeout(ctx)
|
||||
|
@ -357,6 +357,73 @@ int test_events(struct context *ctx)
|
||||
if (print_headings)
|
||||
printf("TEST NUA-12.5: PASSED\n");
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Fetch event, SUBSCRIBE with expires: 0
|
||||
|
||||
A B
|
||||
| |
|
||||
|------SUBSCRIBE---->|
|
||||
|<--------202--------|
|
||||
|<------NOTIFY-------|
|
||||
|-------200 OK------>|
|
||||
| |
|
||||
*/
|
||||
if (print_headings)
|
||||
printf("TEST NUA-12.5.1: event fetch\n");
|
||||
|
||||
SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url),
|
||||
SIPTAG_EVENT_STR("presence"),
|
||||
SIPTAG_ACCEPT_STR("application/pidf+xml"),
|
||||
SIPTAG_EXPIRES_STR("0"),
|
||||
TAG_END());
|
||||
|
||||
run_ab_until(ctx, -1, save_until_notified_and_responded,
|
||||
-1, save_until_subscription);
|
||||
|
||||
/* Client events:
|
||||
nua_subscribe(), nua_i_notify/nua_r_subscribe
|
||||
*/
|
||||
TEST_1(en = event_by_type(a->events->head, nua_i_notify));
|
||||
TEST_1(es = event_by_type(a->events->head, nua_r_subscribe));
|
||||
|
||||
e = es; TEST_E(e->data->e_event, nua_r_subscribe);
|
||||
TEST_1(t = tl_find(e->data->e_tags, nutag_substate));
|
||||
TEST_1(t->t_value == nua_substate_pending ||
|
||||
t->t_value == nua_substate_terminated ||
|
||||
t->t_value == nua_substate_embryonic);
|
||||
|
||||
e = en; TEST_E(e->data->e_event, nua_i_notify);
|
||||
TEST_1(sip = sip_object(e->data->e_msg));
|
||||
n_tags = e->data->e_tags;
|
||||
|
||||
TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence");
|
||||
TEST_1(sip->sip_content_type);
|
||||
TEST_S(sip->sip_content_type->c_type, "application/pidf+xml");
|
||||
TEST_1(sip->sip_payload && sip->sip_payload->pl_data);
|
||||
TEST_1(sip->sip_subscription_state);
|
||||
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
|
||||
TEST_1(tl_find(n_tags, nutag_substate));
|
||||
TEST(tl_find(n_tags, nutag_substate)->t_value,
|
||||
nua_substate_terminated);
|
||||
TEST_1(!en->next || !es->next);
|
||||
free_events_in_list(ctx, a->events);
|
||||
|
||||
/*
|
||||
Server events:
|
||||
nua_i_subscription
|
||||
*/
|
||||
TEST_1(e = b->events->head);
|
||||
TEST_E(e->data->e_event, nua_i_subscription);
|
||||
TEST(tl_gets(e->data->e_tags, NEATAG_SUB_REF(sub), TAG_END()), 1);
|
||||
TEST_1(sub);
|
||||
TEST_1(!e->next);
|
||||
|
||||
free_events_in_list(ctx, b->events);
|
||||
|
||||
if (print_headings)
|
||||
printf("TEST NUA-12.4.1: PASSED\n");
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* 2nd SUBSCRIBE with event id
|
||||
|
||||
@ -370,7 +437,7 @@ int test_events(struct context *ctx)
|
||||
*/
|
||||
/* XXX - we should do this before unsubscribing first one */
|
||||
if (print_headings)
|
||||
printf("TEST NUA-12.4: establishing 2nd subscription\n");
|
||||
printf("TEST NUA-12.4.2: establishing 2nd subscription\n");
|
||||
|
||||
NOTIFIER(b, b_call, b_call->nh,
|
||||
SIPTAG_EVENT_STR("presence"),
|
||||
|
Loading…
x
Reference in New Issue
Block a user