[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