[Freeswitch-svn] [commit] r10829 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/nua libsofia-sip-ua/nua/sofia-sip

FreeSWITCH SVN mikej at freeswitch.org
Tue Dec 16 13:20:22 PST 2008


Author: mikej
Date: Tue Dec 16 16:20:22 2008
New Revision: 10829

Log:
Fri Nov 21 04:52:55 CST 2008  Pekka Pessi <first.last at nokia.com>
  * nua: try to cope if a re-INVITE nor its ACK contain SDP
  
  Some SIP user-agents use INVITE without SDP offer to refresh session.
  By default, NUA sends an offer in 200 OK to such an INVITE and expects
  an answer back in ACK. Now nua tries to recover from such a Offer/Answer
  protocol error.
  
  Also, if NUTAG_REFRESH_WITHOUT_SDP(1) tag is used, and if the re-INVITE was
  received without SDP, no SDP offer is sent in 200 OK.
  
  Thanks for Anthony Minessale for reporting the problem.



Modified:
   freeswitch/trunk/libs/sofia-sip/.update
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h

Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update	(original)
+++ freeswitch/trunk/libs/sofia-sip/.update	Tue Dec 16 16:20:22 2008
@@ -1 +1 @@
-Tue Dec 16 14:46:55 CST 2008
+Tue Dec 16 15:19:47 CST 2008

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c	Tue Dec 16 16:20:22 2008
@@ -1077,6 +1077,71 @@
 }
 END_TEST
 
+START_TEST(call_2_3_3)
+{
+  nua_handle_t *nh;
+  struct message *response;
+
+  s2_case("2.3.3", "Handling re-INVITE without SDP gracefully",
+	  "NUA receives INVITE, "
+	  "re-INVITE without SDP (w/o NUTAG_REFRESH_WITHOUT_SDP(), "
+	  "re-INVITE without SDP (using NUTAG_REFRESH_WITHOUT_SDP(), "
+	  "sends BYE.");
+
+  nh = invite_to_nua(
+    TAG_END());
+
+  s2_request_to(dialog, SIP_METHOD_INVITE, NULL,
+		SIPTAG_USER_AGENT_STR("evil (evil) evil"),
+		TAG_END());
+  
+  nua_respond(nh, SIP_200_OK, TAG_END());
+
+  fail_unless(s2_check_callstate(nua_callstate_completed));
+
+  response = s2_wait_for_response(200, SIP_METHOD_INVITE);
+
+  fail_if(!response);
+  s2_update_dialog(dialog, response);
+  fail_if(!response->sip->sip_content_type);
+  s2_free_message(response);
+
+  fail_if(s2_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END()));
+
+  fail_unless(s2_check_event(nua_i_ack, 200));
+  fail_unless(s2_check_callstate(nua_callstate_ready));
+
+  s2_fast_forward(10);
+
+  nua_set_hparams(nh, NUTAG_REFRESH_WITHOUT_SDP(1), TAG_END());
+  fail_unless(s2_check_event(nua_r_set_params, 200));
+
+  s2_request_to(dialog, SIP_METHOD_INVITE, NULL,
+		SIPTAG_USER_AGENT_STR("evil (evil) evil"),
+		TAG_END());
+  
+  nua_respond(nh, SIP_200_OK, TAG_END());
+
+  fail_unless(s2_check_callstate(nua_callstate_completed));
+
+  response = s2_wait_for_response(200, SIP_METHOD_INVITE);
+
+  fail_if(!response);
+  s2_update_dialog(dialog, response);
+  fail_if(response->sip->sip_content_type);
+  s2_free_message(response);
+
+  fail_if(s2_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END()));
+
+  fail_unless(s2_check_event(nua_i_ack, 200));
+  fail_unless(s2_check_callstate(nua_callstate_ready));
+
+  bye_by_nua(nh, TAG_END());
+
+  nua_handle_destroy(nh);
+}
+END_TEST
+
 
 TCase *session_timer_tcase(void)
 {
@@ -1085,6 +1150,7 @@
   {
     tcase_add_test(tc, call_2_3_1);
     tcase_add_test(tc, call_2_3_2);
+    tcase_add_test(tc, call_2_3_3);
   }
   return tc;
 }

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h	Tue Dec 16 16:20:22 2008
@@ -116,6 +116,7 @@
 
   unsigned sr_offer_sent:2;	/**< We have offered SDP (reliably, if >1) */
   unsigned sr_answer_recv:1;	/**< We have received SDP answer */
+
   unsigned :0;
 
   char const *sr_sdp;		/**< SDP received from client */

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c	Tue Dec 16 16:20:22 2008
@@ -301,6 +301,7 @@
  *   NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n
  *   NUTAG_REFER_EXPIRES() \n
  *   NUTAG_REFER_WITH_ID() \n
+ *   NUTAG_REFRESH_WITHOUT_SDP() \n
  *   NUTAG_REGISTRAR() \n
  *   NUTAG_RETRY_COUNT() \n
  *   NUTAG_SERVICE_ROUTE_ENABLE() \n
@@ -422,6 +423,7 @@
  *   NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n
  *   NUTAG_REFER_EXPIRES() \n
  *   NUTAG_REFER_WITH_ID() \n
+ *   NUTAG_REFRESH_WITHOUT_SDP() \n
  *   NUTAG_REGISTRAR() \n
  *   NUTAG_RETRY_COUNT() \n
  *   NUTAG_SERVICE_ROUTE_ENABLE() \n
@@ -770,6 +772,10 @@
     else if (tag == nutag_update_refresh) {
       NHP_SET(nhp, update_refresh, value != 0);
     }
+    /* NUTAG_REFRESH_WITHOUT_SDP(refresh_without_sdp) */
+    else if (tag == nutag_refresh_without_sdp) {
+      NHP_SET(nhp, refresh_without_sdp, value != 0);
+    }
     /* NUTAG_ENABLEMESSAGE(message_enable) */
     else if (tag == nutag_enablemessage) {
       NHP_SET(nhp, message_enable, value != 0);
@@ -1478,6 +1484,7 @@
  *   NUTAG_PATH_ENABLE() \n
  *   NUTAG_REFER_EXPIRES() \n
  *   NUTAG_REFER_WITH_ID() \n
+ *   NUTAG_REFRESH_WITHOUT_SDP() \n
  *   NUTAG_REGISTRAR() \n
  *   NUTAG_RETRY_COUNT() \n
  *   NUTAG_SERVICE_ROUTE_ENABLE() \n
@@ -1639,6 +1646,7 @@
      TIF(NUTAG_MIN_SE, min_se),
      TIFD(NUTAG_SESSION_REFRESHER, refresher),
      TIF(NUTAG_UPDATE_REFRESH, update_refresh),
+     TIF(NUTAG_REFRESH_WITHOUT_SDP, refresh_without_sdp),
 
      TIF(NUTAG_ENABLEMESSAGE, message_enable),
      TIF(NUTAG_ENABLEMESSENGER, win_messenger_enable),

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h	Tue Dec 16 16:20:22 2008
@@ -82,6 +82,9 @@
   /** no (preference), local or remote */
   enum nua_session_refresher nhp_refresher; 
   unsigned         nhp_update_refresh:1; /**< Use UPDATE to refresh */
+
+  /**< Accept refreshes without SDP */
+  unsigned         nhp_refresh_without_sdp:1;
   
   /* Messaging preferences */
   unsigned     	   nhp_message_enable : 1;
@@ -164,6 +167,7 @@
     unsigned nhb_min_se:1;
     unsigned nhb_refresher:1; 
     unsigned nhb_update_refresh:1;
+    unsigned nhb_refresh_without_sdp:1;
     unsigned nhb_message_enable:1;
     unsigned nhb_win_messenger_enable:1;
     unsigned nhb_message_auto_respond:1;
@@ -179,9 +183,9 @@
     unsigned nhb_keepalive:1;
     unsigned nhb_keepalive_stream:1;
     unsigned nhb_registrar:1;
+    unsigned :0;		/* at most 32 bits before this point */
 
     unsigned nhb_allow:1;
-    unsigned :0;		/* at most 32 bits before this point */
     unsigned nhb_supported:1;
 
     unsigned nhb_allow_events:1;

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c	Tue Dec 16 16:20:22 2008
@@ -171,6 +171,9 @@
 
   /* Offer-Answer status */
   char const     *ss_oa_recv, *ss_oa_sent;
+
+  /**< Version of user SDP from latest successful O/A */
+  unsigned ss_sdp_version;
 } nua_session_usage_t;
 
 static char const Offer[] = "offer", Answer[] = "answer";
@@ -964,11 +967,14 @@
       /* XXX */
       sdp = NULL;
     }
-    else if (soa_activate(nh->nh_soa, NULL) < 0)
+    else if (soa_activate(nh->nh_soa, NULL) < 0) {
       /* XXX - what about errors? */
       LOG3("error activating media after");
-    else
+    }
+    else {
+      ss->ss_sdp_version = soa_get_user_version(nh->nh_soa);
       LOG5("processed SDP");
+    }
   }
   else if (cr->cr_method != sip_method_invite) {
     /* If non-invite request did not have offer, ignore SDP in response */
@@ -1309,7 +1315,8 @@
       ;
     else if (nh->nh_soa && soa_is_complete(nh->nh_soa)) {
       /* signal SOA that O/A round(s) is (are) complete */
-	soa_activate(nh->nh_soa, NULL);
+      if (soa_activate(nh->nh_soa, NULL) >= 0)
+	ss->ss_sdp_version = soa_get_user_version(nh->nh_soa);
     }
     else if (nh->nh_soa == NULL
 	     /* NUA does not necessarily know dirty details */
@@ -1741,7 +1748,8 @@
     }
     else {
       answer_sent = 1;
-      soa_activate(nh->nh_soa, NULL);
+      if (soa_activate(nh->nh_soa, NULL) >= 0)
+	ss->ss_sdp_version = soa_get_user_version(nh->nh_soa);
     }
   }
   else if (nh->nh_soa == NULL) {
@@ -1967,6 +1975,8 @@
   process_ack_or_cancel(nua_server_request_t *, nta_incoming_t *, 
 			sip_t const *),
   process_ack(nua_server_request_t *, nta_incoming_t *, sip_t const *),
+  process_ack_error(nua_server_request_t *sr, msg_t *ackmsg,
+		    int status, char const *phrase, char const *reason),
   process_cancel(nua_server_request_t *, nta_incoming_t *, sip_t const *),
   process_timeout(nua_server_request_t *, nta_incoming_t *),
   process_prack(nua_server_request_t *,
@@ -2207,7 +2217,7 @@
   msg_t *msg = sr->sr_response.msg; 
   sip_t *sip = sr->sr_response.sip; 
 
-  int reliable = 0, offer = 0, answer = 0, early_answer = 0, extra = 0;
+  int reliable = 0, maybe_answer = 0, offer = 0, answer = 0, extra = 0;
 
   enter;
 
@@ -2217,8 +2227,11 @@
     return nua_base_server_respond(sr, tags);
   }
 
-  if (nua_invite_server_is_100rel(sr, tags)) {
-    reliable = 1, early_answer = 1;
+  if (200 <= sr->sr_status && sr->sr_status < 300) {
+    reliable = 1, maybe_answer = 1;
+  }
+  else if (nua_invite_server_is_100rel(sr, tags)) {
+    reliable = 1, maybe_answer = 1;
   }
   else if (!nh->nh_soa || sr->sr_status >= 300) {
     if (sr->sr_neutral)
@@ -2234,10 +2247,10 @@
 	    SOATAG_USER_SDP_STR_REF(user_sdp_str),
 	    TAG_END());
 
-    early_answer = user_sdp || user_sdp_str;
+    maybe_answer = user_sdp || user_sdp_str;
   }
   else {
-    early_answer = NH_PGET(nh, early_answer);
+    maybe_answer = NH_PGET(nh, early_answer);
   }
 
   if (!nh->nh_soa) {
@@ -2259,11 +2272,12 @@
     tagi_t const *t = tl_find_last(tags, nutag_include_extra_sdp);
     extra = t && t->t_value;
   }
-  else if (sr->sr_offer_recv && !sr->sr_answer_sent && early_answer) {
+  else if (sr->sr_offer_recv && !sr->sr_answer_sent && maybe_answer) {
     /* Generate answer */ 
     if (soa_generate_answer(nh->nh_soa, NULL) >= 0 &&
 	soa_activate(nh->nh_soa, NULL) >= 0) {
       answer = 1;      /* signal that O/A answer sent (answer to invite) */
+      /* ss_sdp_version is updated only after answer is sent reliably */
     }
     /* We have an error! */
     else if (sr->sr_status >= 200) {
@@ -2288,12 +2302,16 @@
       /* 1xx - we don't have to send answer */
     }
   }
-  else if (sr->sr_offer_recv && sr->sr_answer_sent == 1 && early_answer) {
+  else if (sr->sr_offer_recv && sr->sr_answer_sent == 1 && maybe_answer) {
     /* The answer was sent unreliably, keep sending it */
     answer = 1;
   }
   else if (!sr->sr_offer_recv && !sr->sr_offer_sent && reliable) {
-    /* Generate offer */
+    if (200 <= sr->sr_status && nua_callstate_ready <= ss->ss_state &&
+	NH_PGET(nh, refresh_without_sdp))
+      /* This is a re-INVITE without SDP - do not try to send offer in 200 */;
+    else
+      /* Generate offer */
     if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0)
       sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase);
     else
@@ -2307,6 +2325,9 @@
       sr->sr_offer_sent = 1 + reliable, ss->ss_oa_sent = Offer;
     else if (answer)
       sr->sr_answer_sent = 1 + reliable, ss->ss_oa_sent = Answer;
+
+    if (answer && reliable)
+      ss->ss_sdp_version = soa_get_user_version(nh->nh_soa);
   }
 
   if (reliable && sr->sr_status < 200) {
@@ -2340,16 +2361,15 @@
 int nua_invite_server_is_100rel(nua_server_request_t *sr, tagi_t const *tags)
 {
   nua_handle_t *nh = sr->sr_owner;
-  sip_t const *sip = sr->sr_response.sip;
   sip_require_t *require = sr->sr_request.sip->sip_require;
   sip_supported_t *supported = sr->sr_request.sip->sip_supported;
 
   if (sr->sr_status >= 200)
-    return 1;
+    return 0;
   else if (sr->sr_status == 100)
     return 0;
 
-  if (sip_has_feature(sip->sip_require, "100rel"))
+  if (sip_has_feature(sr->sr_response.sip->sip_require, "100rel"))
     return 1;
 
   if (require == NULL && supported == NULL)
@@ -2473,7 +2493,7 @@
  * 
  * @END_NUA_EVENT
  */
-
+static
 int process_ack(nua_server_request_t *sr,
 		nta_incoming_t *irq,
 		sip_t const *sip)
@@ -2489,7 +2509,6 @@
   if (sr->sr_offer_sent && !sr->sr_answer_recv) {
     char const *sdp;
     size_t len;
-    int error;
 
     if (session_get_description(sip, &sdp, &len))
       recv = Answer;
@@ -2499,32 +2518,45 @@
       ss->ss_oa_recv = recv;
     }
 
-    if (nh->nh_soa == NULL)
+    if (nh->nh_soa == NULL) 
       ;
-    else if (recv == NULL ||
-	     soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0 ||
-	     soa_process_answer(nh->nh_soa, NULL) < 0 ||
-	     soa_activate(nh->nh_soa, NULL) < 0) {
-      int status; char const *phrase, *reason;
+    else if (recv == NULL ) {
+      if (ss->ss_state >= nua_callstate_ready &&
+	  soa_get_user_version(nh->nh_soa) == ss->ss_sdp_version &&
+	  soa_process_reject(nh->nh_soa, NULL) >= 0) {
+	url_t const *m;
 
-      status = soa_error_as_sip_response(nh->nh_soa, &phrase);
-      reason = soa_error_as_sip_reason(nh->nh_soa);
+	/* The re-INVITE was a refresh and re-INVITEr ignored our offer */
+	ss->ss_oa_sent = NULL; 
 
-      nua_stack_event(nh->nh_nua, nh, msg,
-		      nua_i_ack, status, phrase, NULL);
-      nua_stack_event(nh->nh_nua, nh, NULL,
-		      nua_i_media_error, status, phrase, NULL);
+	if (sr->sr_request.sip->sip_contact)
+	  m = sr->sr_request.sip->sip_contact->m_url;
+	else
+	  m = sr->sr_request.sip->sip_from->a_url;
 
-      ss->ss_reporting = 1;	/* We report terminated state here if BYE fails */
-      error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL);
-      ss->ss_reporting = 0;
+	SU_DEBUG_3(("nua(%p): re-INVITEr ignored offer in our %u response "
+		    "(Contact: <" URL_PRINT_FORMAT  ">)\n", 
+		    (void *)nh, sr->sr_status, URL_PRINT_ARGS(m)));
+	if (sr->sr_request.sip->sip_user_agent)
+	  SU_DEBUG_3(("nua(%p): re-INVITE: \"User-Agent: %s\"\n", (void *)nh,
+		      sr->sr_request.sip->sip_user_agent->g_string));
+      }      
+      else 
+	return process_ack_error(sr, msg, 488, "Offer-Answer error", 
+				 "SIP;cause=488;text=\"No answer to offer\"");
+    }
+    else if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) >= 0 &&
+	     soa_process_answer(nh->nh_soa, NULL) >= 0 &&
+	     soa_activate(nh->nh_soa, NULL) >= 0) {
+      ss->ss_sdp_version = soa_get_user_version(nh->nh_soa);      
+    }
+    else {
+      int status; char const *phrase, *reason;
 
-      signal_call_state_change(nh, ss, 488, "Offer-Answer Error",
-			       error
-			       ? nua_callstate_terminated
-			       : nua_callstate_terminating);
+      status = soa_error_as_sip_response(nh->nh_soa, &phrase);
+      reason = soa_error_as_sip_reason(nh->nh_soa);
 
-      return 0;
+      return process_ack_error(sr, msg, status, phrase, reason);
     }
   }
 
@@ -2540,6 +2572,38 @@
   return 0;
 }
 
+static int 
+process_ack_error(nua_server_request_t *sr,
+		  msg_t *ackmsg,
+		  int status,
+		  char const *phrase,
+		  char const *reason)
+{
+  nua_handle_t *nh = sr->sr_owner;
+  nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage);
+  int error;
+  
+  nua_stack_event(nh->nh_nua, nh, ackmsg,
+		  nua_i_ack, status, phrase, NULL);
+  nua_stack_event(nh->nh_nua, nh, NULL,
+		  nua_i_media_error, status, phrase, NULL);
+
+  if (reason) ss->ss_reason = reason;
+  ss->ss_reporting = 1;	
+  error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL);
+  ss->ss_reporting = 0;
+
+  signal_call_state_change(nh, ss,
+			   488, "Offer-Answer Error",
+			   /* We report terminated state if BYE failed */
+			   error
+			   ? nua_callstate_terminated
+			   : nua_callstate_terminating);
+
+  return 0;
+}
+
+
 /** @NUA_EVENT nua_i_cancel
  *
  * Incoming INVITE has been cancelled by the client.
@@ -2809,8 +2873,10 @@
     signal_call_state_change(nh, ss,
 			     status, phrase, 
 			     ss->ss_state);
-    if (nh->nh_soa)
+    if (nh->nh_soa) {
       soa_activate(nh->nh_soa, NULL);
+      ss->ss_sdp_version = soa_get_user_version(nh->nh_soa);      
+    }
   }
 
   if (status < 200 || 300 <= status)
@@ -3469,6 +3535,7 @@
     }
     else {
       sr->sr_answer_sent = 1, ss->ss_oa_sent = Answer;
+      ss->ss_sdp_version = soa_get_user_version(nh->nh_soa);      
     }
   }
 

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c	Tue Dec 16 16:20:22 2008
@@ -182,7 +182,8 @@
  * UPDATE requests.
  * Settings:
  * - NUTAG_MIN_SE(), NUTAG_SESSION_REFRESHER(),
- *   NUTAG_SESSION_TIMER(), NUTAG_UPDATE_REFRESH()
+ *   NUTAG_SESSION_TIMER(), NUTAG_UPDATE_REFRESH(),
+ *   NUTAG_REFRESH_WITHOUT_SDP(),
  * - "timer" in NUTAG_SUPPORTED()/SIPTAG_SUPPORTED()
  * Specifications:
  * - @RFC4028
@@ -954,6 +955,11 @@
  * @SessionExpires header sends a re-INVITE requests (or an UPDATE
  * request if NUTAG_UPDATE_REFRESH(1) parameter tag has been set).
  *
+ * Some SIP user-agents use INVITE without SDP offer to refresh session.
+ * By default, NUA sends an offer in 200 OK to such an INVITE and expects
+ * an answer back in ACK. If NUTAG_REFRESH_WITHOUT_SDP(1) tag is used,
+ * no SDP offer is sent in 200 OK if re-INVITE was received without SDP.
+ *
  * @par When to Use NUTAG_SESSION_TIMER()?
  *
  * The session time extension is enabled ("timer" feature tag is included in
@@ -1106,7 +1112,7 @@
  * Corresponding tag taking reference parameter is NUTAG_UPDATE_REFRESH_REF().
  *
  * @sa #nua_r_update, NUTAG_SESSION_TIMER(), NUTAG_MIN_SE_REF(),
- * NUTAG_UPDATE_REFRESH(), @RFC4028, @SessionExpires, @MinSE
+ * NUTAG_SESSION_REFRESHER(), @RFC4028, @SessionExpires, @MinSE
  */
 tag_typedef_t nutag_update_refresh = BOOLTAG_TYPEDEF(update_refresh);
 
@@ -1115,6 +1121,45 @@
  */
 
 
+/**@def NUTAG_REFRESH_WITHOUT_SDP(x)
+ *
+ * Do not send offer in response if re-INVITE was received without SDP.
+ *
+ * Some SIP user-agents use INVITE without SDP offer to refresh session.
+ * By default, NUA sends an offer in 200 OK to such an INVITE and expects
+ * an answer back in ACK.
+ *
+ * If NUTAG_REFRESH_WITHOUT_SDP(1) tag is used, no SDP offer is sent in 200
+ * OK if re-INVITE was received without SDP.
+ *
+ * @par Used with
+ *    nua_handle(), nua_invite(), nua_update(), nua_respond() \n
+ *    nua_set_params() or nua_set_hparams() \n
+ *    nua_get_params() or nua_get_hparams()
+ *
+ * See nua_set_hparams() for a complete list of all the nua operations that
+ * accept this tag.
+ *
+ * @par Parameter type
+ *    int (boolean: nonzero is true, zero is false)
+ *
+ * @par Values
+ *    - 1 (true, do not try to send offer in response to re-INVITE)
+ *    - 0 (false, always use SDP offer-answer in re-INVITEs)
+ *
+ * Corresponding tag taking reference parameter is NUTAG_REFRESH_WITHOUT_SDP_REF().
+ *
+ * @sa #nua_r_update, NUTAG_SESSION_TIMER(), NUTAG_MIN_SE_REF(),
+ * NUTAG_SESSION_REFRESHER(), NUTAG_UPDATE_REFRESH(), @RFC4028,
+ * @SessionExpires, @MinSE
+ */
+tag_typedef_t nutag_refresh_without_sdp = BOOLTAG_TYPEDEF(refresh_without_sdp);
+
+/**@def NUTAG_REFRESH_WITHOUT_SDP_REF(x)
+ * Reference tag for NUTAG_REFRESH_WITHOUT_SDP_REF().
+ */
+
+
 /**@def NUTAG_REFER_EXPIRES()
  *
  * Default lifetime for implicit subscriptions created by REFER.

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h	Tue Dec 16 16:20:22 2008
@@ -183,6 +183,12 @@
 #define NUTAG_UPDATE_REFRESH_REF(x) nutag_update_refresh_ref, tag_bool_vr((&(x)))
 SOFIAPUBVAR tag_typedef_t nutag_update_refresh_ref;
 
+#define NUTAG_REFRESH_WITHOUT_SDP(x) nutag_refresh_without_sdp, tag_bool_v((x))
+SOFIAPUBVAR tag_typedef_t nutag_refresh_without_sdp;
+#define NUTAG_REFRESH_WITHOUT_SDP_REF(x) \
+  nutag_refresh_without_sdp_ref, tag_bool_vr((&(x)))
+SOFIAPUBVAR tag_typedef_t nutag_refresh_without_sdp_ref;
+
 #define NUTAG_AUTOALERT(x)      nutag_autoalert, tag_bool_v(x)
 SOFIAPUBVAR tag_typedef_t nutag_autoalert;
 #define NUTAG_AUTOALERT_REF(x)  nutag_autoalert_ref, tag_bool_vr(&(x))



More information about the Freeswitch-svn mailing list