[Freeswitch-svn] [commit] r8285 - freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua
Freeswitch SVN
mikej at freeswitch.org
Wed May 7 08:26:43 EDT 2008
Author: mikej
Date: Wed May 7 08:26:42 2008
New Revision: 8285
Modified:
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/test_sip_events.c
Log:
Thu Apr 24 11:31:48 EDT 2008 first.last at 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.
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c Wed May 7 08:26:42 2008
@@ -558,9 +558,6 @@
}
}
- 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 @@
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);
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c Wed May 7 08:26:42 2008
@@ -248,15 +248,18 @@
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;
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c Wed May 7 08:26:42 2008
@@ -607,6 +607,27 @@
}
}
+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 @@
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 @@
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 @@
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);
@@ -1165,6 +1197,235 @@
}
/* ---------------------------------------------------------------------- */
+
+/*
+ * 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 */
int accept_notify(CONDITION_PARAMS);
@@ -1830,6 +2091,7 @@
|| 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)
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/test_sip_events.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/test_sip_events.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/test_sip_events.c Wed May 7 08:26:42 2008
@@ -358,6 +358,73 @@
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
A B
@@ -370,7 +437,7 @@
*/
/* 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"),
More information about the Freeswitch-svn
mailing list