[Freeswitch-svn] [commit] r7368 - in freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua: nta nta/sofia-sip sip soa soa/sofia-sip sresolv sresolv/sofia-resolv su su/sofia-sip

Freeswitch SVN mikej at freeswitch.org
Sat Jan 26 14:48:15 EST 2008


Author: mikej
Date: Sat Jan 26 14:48:14 2008
New Revision: 7368

Modified:
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta_tag.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sip/sip_util.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa_static.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa_tag.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/sofia-sip/soa_session.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/test_soa.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sofia-resolv/sres.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sofia-resolv/sres_cache.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_addrinfo.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_addrinfo.c

Log:
Update back to sofia tree now that we have identified the cause of the segfaults:

Fri Jan 11 09:12:01 EST 2008  Bernhard Suttner <suttner at comdasys.com>
  * Using # in SOATAG_HOLD to set media as inactive instead of sendonly

Fri Jan 11 09:15:18 EST 2008  Pekka.Pessi at nokia.com
  * soa_tag.c: documented SOATAG_HOLD() inactive mode

Fri Jan 11 09:28:46 EST 2008  Pekka.Pessi at nokia.com
  * su_addrinfo.c: if su_getaddrinfo() service is NULL, try both with "0" and NULL

Fri Jan 11 12:11:12 EST 2008  Pekka.Pessi at nokia.com
  * nta.c: NetModule hack re-prioritizing SRV records
  
  Original hack by Stefan Leuenberger <Stefan.Leuenberger at netmodule.com>.
  
  The hack reprioritizes the SRV records used with transaction in case a
  server refuses connection or it does not answer.

Thu Jan 17 11:40:46 EST 2008  Pekka Pessi <Pekka.Pessi at nokia.com>
  * soa_static.c: cleaned inactive hold, added tests

Mon Jan 21 14:06:35 EST 2008  Pekka.Pessi at nokia.com
  * soa.c: using session state in soa_set_activity()
  
  The media mode bits are set using (local) session description instead of
  remote offer/answer when O/A has been completed.

Mon Jan 21 14:08:08 EST 2008  Pekka.Pessi at nokia.com
  * soa_static.c: soa_sdp_mode_set() now includes wanted media state in offer
  
  The wanted media state is based on original user SDP and SOATAG_HOLD()
  content. Removed soa_sdp_mode_set_is_needed(), using dry-run parameter
  instead.
  
Tue Jan 22 11:15:04 EST 2008  Pekka.Pessi at nokia.com
  * sip_util.c: updated sip_response_terminates_dialog() as per RFC 5057.
  
  Changes handling of 423 in case of SUBSCRIBE.

Tue Jan 22 11:35:44 EST 2008  Pekka.Pessi at nokia.com
  * test_soa.c: testing hold with inactive, offered mode and setting remote activity flags while in hold

Tue Jan 22 13:57:38 EST 2008  Pekka.Pessi at nokia.com
  * sres: added ttl parameter to sres_set_cached_srv_priority() and sres_cache_set_srv_priority().

Tue Jan 22 13:59:44 EST 2008  Pekka.Pessi at nokia.com
  * nta.c: added NTATAG_GRAYLIST(). 
  
  Use NTATAG_GRAYLIST() as ttl value for sres_set_cached_srv_priority().

Wed Jan 23 10:07:30 EST 2008  Pekka Pessi <Pekka.Pessi at nokia.com>
  * soa_static.c: fixed signedness error

Wed Jan 23 11:05:23 EST 2008  Pekka.Pessi at nokia.com
  * nta.c: ignore tags in nta_leg_by_dialog() if they are empty strings

Wed Jan 23 11:05:58 EST 2008  Pekka.Pessi at nokia.com
  * nta.c: asserting in proper place when handling queue tail




Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta.c	Sat Jan 26 14:48:14 2008
@@ -338,7 +338,7 @@
  * NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(),
  * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(),
  * NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(),
- * NTATAG_EXTRA_100(),
+ * NTATAG_EXTRA_100(), NTATAG_GRAYLIST(),
  * NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS()
  * NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(), 
  * NTATAG_REL100(), 
@@ -400,6 +400,7 @@
     agent->sa_t4              = NTA_SIP_T4;
     agent->sa_t1x64 	      = 64 * NTA_SIP_T1;
     agent->sa_timer_c         = 185 * 1000;
+    agent->sa_graylist        = 600;
     agent->sa_drop_prob       = 0;
     agent->sa_is_a_uas        = 0;
     agent->sa_progress        = 60 * 1000;
@@ -894,7 +895,7 @@
  * NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(),
  * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(),
  * NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(),
- * NTATAG_EXTRA_100(),
+ * NTATAG_EXTRA_100(), NTATAG_GRAYLIST(),
  * NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS()
  * NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(), 
  * NTATAG_REL100(), 
@@ -944,6 +945,7 @@
   unsigned sip_t4     = agent->sa_t4;
   unsigned sip_t1x64  = agent->sa_t1x64;
   unsigned timer_c    = agent->sa_timer_c;
+  unsigned graylist   = agent->sa_graylist;
   unsigned blacklist  = agent->sa_blacklist;
   int ua              = agent->sa_is_a_uas;
   unsigned progress   = agent->sa_progress;
@@ -987,6 +989,7 @@
 	      NTATAG_DEBUG_DROP_PROB_REF(drop_prob),
 	      NTATAG_DEFAULT_PROXY_REF(proxy),
 	      NTATAG_EXTRA_100_REF(extra_100),
+	      NTATAG_GRAYLIST_REF(graylist),
 	      NTATAG_MAXSIZE_REF(maxsize),
 	      NTATAG_MAX_PROCEEDING_REF(max_proceeding),
 	      NTATAG_MAX_FORWARDS_REF(max_forwards),
@@ -1140,6 +1143,12 @@
     outgoing_queue_adjust(agent, agent->sa_out.inv_proceeding, timer_c);
   }
 
+  if (graylist > 24 * 60 * 60)
+    graylist = 24 * 60 * 60;
+  agent->sa_graylist = graylist;
+
+  if (blacklist > 24 * 60 * 60)
+    blacklist = 24 * 60 * 60;
   agent->sa_blacklist = blacklist;
 
   if (progress == 0)
@@ -1202,7 +1211,7 @@
  * NTATAG_CANCEL_2543_REF(), NTATAG_CANCEL_487_REF(),
  * NTATAG_CLIENT_RPORT_REF(), NTATAG_CONTACT_REF(), 
  * NTATAG_DEBUG_DROP_PROB_REF(), NTATAG_DEFAULT_PROXY_REF(),
- * NTATAG_EXTRA_100_REF(),
+ * NTATAG_EXTRA_100_REF(), NTATAG_GRAYLIST_REF(),
  * NTATAG_MAXSIZE_REF(), NTATAG_MAX_FORWARDS_REF(), NTATAG_MCLASS_REF(),
  * NTATAG_MERGE_482_REF(), NTATAG_MAX_PROCEEDING_REF(),
  * NTATAG_PASS_100_REF(), NTATAG_PASS_408_REF(), NTATAG_PRELOAD_REF(),
@@ -1251,6 +1260,7 @@
 	     NTATAG_DEBUG_DROP_PROB(agent->sa_drop_prob),
 	     NTATAG_DEFAULT_PROXY(agent->sa_default_proxy),
 	     NTATAG_EXTRA_100(agent->sa_extra_100),
+	     NTATAG_GRAYLIST(agent->sa_graylist),
 	     NTATAG_MAXSIZE(agent->sa_maxsize),
 		 NTATAG_MAX_PROCEEDING(agent->sa_max_proceeding),
 	     NTATAG_MAX_FORWARDS(agent->sa_max_forwards->mf_count),
@@ -4123,6 +4133,9 @@
  *                     it must math
  * @param local_uri    ignored
  *
+ * @note
+ * If @a remote_tag or @a local_tag is an empty string (""), the tag is
+ * ignored when matching legs.
  */
 nta_leg_t *nta_leg_by_dialog(nta_agent_t const *agent,
 			     url_t const *request_uri,
@@ -4224,9 +4237,9 @@
     if (!remote_tag != !from_tag && !local_tag != !to_tag)
       continue;
 
-    if (local_tag && to_tag && strcasecmp(local_tag, to_tag))
+    if (local_tag && to_tag && strcasecmp(local_tag, to_tag) && to_tag[0])
       continue;
-    if (remote_tag && from_tag && strcasecmp(remote_tag, from_tag))
+    if (remote_tag && from_tag && strcasecmp(remote_tag, from_tag) && from_tag[0])
       continue;
 
     if (leg_url && request_uri && url_cmp(leg_url, request_uri))
@@ -7649,6 +7662,7 @@
   if (outgoing_is_queued(orq))
     outgoing_remove(orq);
 
+  assert(orq->orq_next == NULL);
   assert(*queue->q_tail == NULL);
 
   orq->orq_timeout = set_timeout(orq->orq_agent, queue->q_timeout);
@@ -7672,7 +7686,7 @@
   if ((*orq->orq_prev = orq->orq_next))
     orq->orq_next->orq_prev = orq->orq_prev;
   else
-    orq->orq_queue->q_tail = orq->orq_prev, assert(!*orq->orq_queue->q_tail);
+    orq->orq_queue->q_tail = orq->orq_prev;
 
   orq->orq_queue->q_length--;
   orq->orq_next = NULL;
@@ -8828,8 +8842,8 @@
   char const *sq_proto;
   char const *sq_domain;
   char     sq_port[6];		/* port number */
-
-  uint16_t sq_type;
+  uint16_t sq_otype;		/* origin type of query data (0 means request) */
+  uint16_t sq_type;		/* query type */
   uint16_t sq_priority;		/* priority or preference  */
   uint16_t sq_weight;		/* preference or weight */
 };
@@ -9060,6 +9074,65 @@
   outgoing_reset_timer(orq);
   outgoing_queue(orq->orq_agent->sa_out.resolving, orq);
 
+  if (orq->orq_status > 0)
+    /* PP: don't hack priority if a preliminary response has been received */
+    ;
+  else if (orq->orq_agent->sa_graylist == 0)
+    /* PP: priority hacking disabled */
+    ;
+  /* NetModule hack: 
+   * Move server that did not work to end of queue in sres cache
+   *
+   * the next request does not try to use the server that is currently down
+   *
+   * @TODO: fix cases with only A or AAAA answering, or all servers down.
+   */
+  else if (sr && sr->sr_target) {
+    struct sipdns_query *sq;
+
+    /* find latest A/AAAA record */
+    sq = sr->sr_head;
+    if (!sq || (sr->sr_a_aaaa1 != sr->sr_a_aaaa2 && sq->sq_type == sr->sr_a_aaaa1))
+	sq = sr->sr_done;	
+    
+    if (sq && sq->sq_otype == sres_type_srv) {
+      char const *target = sq->sq_domain, *proto = sq->sq_proto;
+      unsigned prio = sq->sq_priority, maxprio = prio;
+
+      SU_DEBUG_5(("nta: no response from %s:%s;transport=%s\n", target, sq->sq_port, proto));
+
+      for (sq = sr->sr_head; sq; sq = sq->sq_next) 
+	if (sq->sq_otype == sres_type_srv && sq->sq_priority > maxprio)
+	  maxprio = sq->sq_priority;
+
+      for (sq = sr->sr_done; sq; sq = sq->sq_next)
+	if (sq->sq_otype == sres_type_srv && sq->sq_priority > maxprio)
+	  maxprio = sq->sq_priority;
+
+      for (sq = sr->sr_done; sq; sq = sq->sq_next) {
+	int modified;
+
+	if (sq->sq_type != sres_type_srv || strcmp(proto, sq->sq_proto))
+	  continue;
+
+	/* modify the SRV record(s) corresponding to the latest A/AAAA record */
+	modified = sres_set_cached_srv_priority(
+	  orq->orq_agent->sa_resolver, 
+	  sq->sq_domain, 
+	  target,
+	  sq->sq_port[0] ? (uint16_t)strtoul(sq->sq_port, NULL, 10) : 0,
+	  orq->orq_agent->sa_graylist,
+	  maxprio + 1);
+
+	if (modified >= 0)
+	  SU_DEBUG_3(("nta: reduced priority of %d %s SRV records (increase value to %u)\n",
+		      modified, sq->sq_domain, maxprio + 1));
+	else
+	  SU_DEBUG_3(("nta: failed to reduce %s SRV priority\n", sq->sq_domain));
+      }
+    }
+  }
+
   return outgoing_resolve_next(orq);
 }
 
@@ -9338,6 +9411,7 @@
     sq = su_zalloc(home, (sizeof *sq) + rlen);
 
     *tail = sq, tail = &sq->sq_next;    
+    sq->sq_otype = sres_type_naptr;
     sq->sq_priority = na->na_prefer;
     sq->sq_weight = j;
     sq->sq_type = type;
@@ -9438,11 +9512,11 @@
     if (sq) {
       *tail = sq, tail = &sq->sq_next;
 
+      sq->sq_otype = sres_type_srv;
       sq->sq_type = sr->sr_a_aaaa1;
       sq->sq_proto = sq0->sq_proto;
       sq->sq_domain = memcpy(sq + 1, srv->srv_target, tlen);
       snprintf(sq->sq_port, sizeof(sq->sq_port), "%u", srv->srv_port);
-
       sq->sq_priority = srv->srv_priority;
       sq->sq_weight = srv->srv_weight;
     }

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h	Sat Jan 26 14:48:14 2008
@@ -167,6 +167,8 @@
   /** SIP timer C - interval between provisional responses receivedxs */
   unsigned              sa_timer_c;
 
+  /** Graylisting period */
+  unsigned              sa_graylist;
   /** Blacklisting period */
   unsigned              sa_blacklist;
 

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta_tag.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta_tag.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta_tag.c	Sat Jan 26 14:48:14 2008
@@ -643,6 +643,31 @@
  */
 tag_typedef_t ntatag_timer_c = UINTTAG_TYPEDEF(timer_c);
 
+/**@def NTATAG_GRAYLIST(x)
+ *
+ * Avoid failed servers.
+ *
+ * The NTATAG_GRAYLIST() provides the time that the servers are avoided
+ * after a request sent to them has been failed. Avoiding means that if a
+ * domain provides multiple servers, the failed servers are tried last.
+ *
+ * @par Used with
+ *    nua_create(), nua_set_params(),
+ *    nta_agent_create(), nta_agent_set_params()
+ *
+ * @par Parameter type
+ *     unsigned int
+ *
+ * @par Values
+ *    - Number of seconds that server is kept in graylist, from 0 to 86400.
+ *
+ * @par Default Value
+ *    - 600 (graylist server for 10 minutes)
+ *
+ * @sa NTATAG_BLACKLIST(), NTATAG_TIMEOUT_408()
+ */
+tag_typedef_t ntatag_graylist = UINTTAG_TYPEDEF(graylist);
+
 /**@def NTATAG_BLACKLIST(x)
  *
  * Add Retry-After header to error responses returned to application.
@@ -660,7 +685,7 @@
  *     unsigned int
  *
  * @par Values
- *    - Value of delta-seconds in @RetryAfter header
+ *    - Value of @i delta-seconds in @RetryAfter header, from 0 to 86400
  *
  * @par Default Value
  *    - 0 (no Retry-After is included)

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h	Sat Jan 26 14:48:14 2008
@@ -203,6 +203,12 @@
 NTA_DLL extern tag_typedef_t ntatag_timer_c_ref;
 #define NTATAG_TIMER_C_REF(x) ntatag_timer_c_ref, tag_uint_vr(&(x))
 
+NTA_DLL extern tag_typedef_t ntatag_graylist;
+#define NTATAG_GRAYLIST(x)  ntatag_graylist, tag_uint_v((x))
+
+NTA_DLL extern tag_typedef_t ntatag_graylist_ref;
+#define NTATAG_GRAYLIST_REF(x) ntatag_graylist_ref, tag_uint_vr(&(x))
+
 NTA_DLL extern tag_typedef_t ntatag_blacklist;
 #define NTATAG_BLACKLIST(x)  ntatag_blacklist, tag_uint_v((x))
 

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sip/sip_util.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sip/sip_util.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sip/sip_util.c	Sat Jan 26 14:48:14 2008
@@ -883,8 +883,7 @@
  * decide whether to gracefully terminate or not, the
  * @a *return_graceful_terminate_usage is left unmodified.
  *
- * @sa 
- * http://www.ietf.org/internet-drafts/draft-ietf-sipping-dialogusage-02.txt
+ * @RFC 5057
  */
 int sip_response_terminates_dialog(int response_code,
 				   sip_method_t method,
@@ -1060,8 +1059,6 @@
       usage in an existing dialog, no new usage is created and existing
       usages are unaffected.
     */
-    *return_graceful_terminate_usage = 0;
-    return 0;
 
   case 423: /** @par 423 Interval Too Brief 
 
@@ -1070,8 +1067,6 @@
       subscribe usage is not destroyed (or otherwise affected).  No
       other usages of the dialog are affected.
     */
-    *return_graceful_terminate_usage = 0;
-    return sip_method_subscribe == method ? terminate_usage : no_effect;
 
   case 428: /** @par 428 Use Identity Header
 
@@ -1079,8 +1074,6 @@
       the usage.  The usage is not affected.  The dialog is only
       affected by a change in its local @CSeq.  No other usages of the
       dialog are affected. */
-    *return_graceful_terminate_usage = 0;
-    return 0;
 
   case 429: /** @par 429 Provide Referrer Identity 
 

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa.c	Sat Jan 26 14:48:14 2008
@@ -70,10 +70,6 @@
 /* ======================================================================== */
 
 /* Internal prototypes */
-void soa_set_activity(soa_session_t *ss,
-		      sdp_media_t const *,
-		      int remote);
-
 su_inline int soa_media_is_ready(soa_session_t const *ss);
 
 enum soa_sdp_kind { 
@@ -1171,7 +1167,7 @@
   if (!new_version)
     return 0;
     
-  soa_set_activity(ss, sdp->sdp_media, 1);
+  soa_set_activity(ss, sdp->sdp_media, soa_activity_remote);
 
   ss->ss_remote_version++;
   
@@ -1454,7 +1450,7 @@
   if (!sdp)
     return -1;
 
-  soa_set_activity(ss, sdp->sdp_media, 0);
+  soa_set_activity(ss, sdp->sdp_media, soa_activity_local); /* Wanted activity */
 
   ss->ss_offer_sent = 1;
   ss->ss_answer_recv = 0;
@@ -1542,8 +1538,7 @@
     su_free(ss->ss_home, ss->ss_rsession);
   ss->ss_rsession = rsession;
 
-  soa_set_activity(ss, l_sdp->sdp_media, 0);
-  soa_set_activity(ss, r_sdp->sdp_media, 1);
+  soa_set_activity(ss, l_sdp->sdp_media, soa_activity_session);
 
   ss->ss_offer_recv = 1;
   ss->ss_answer_sent = 1;
@@ -1624,8 +1619,7 @@
     su_free(ss->ss_home, ss->ss_rsession);
   ss->ss_rsession = rsession;
 
-  soa_set_activity(ss, l_sdp->sdp_media, 0);
-  soa_set_activity(ss, r_sdp->sdp_media, 1);
+  soa_set_activity(ss, l_sdp->sdp_media, soa_activity_session);
 
   ss->ss_answer_recv = 1;
   ss->ss_complete = 1;
@@ -1692,7 +1686,7 @@
   if (!l_sdp)
     return -1;
 
-  soa_set_activity(ss, l_sdp->sdp_media, 0);
+  soa_set_activity(ss, l_sdp->sdp_media, soa_activity_session);
 
   ss->ss_offer_sent = 0;
 
@@ -1783,8 +1777,7 @@
   ss->ss_oa_rounds = 0;
 
   soa_description_free(ss, ss->ss_remote);
-  soa_set_activity(ss, NULL, 0);
-  soa_set_activity(ss, NULL, 1);
+  soa_set_activity(ss, NULL, soa_activity_session);
 }
 
 /** Return true if the SDP Offer/Answer negotation is complete.
@@ -1889,56 +1882,75 @@
 
 void soa_set_activity(soa_session_t *ss,
 		      sdp_media_t const *m,
-		      int remote)
+		      enum soa_activity activity)
 {
   struct soa_media_activity *ma;
   sdp_connection_t const *c;
-  int mode;
-  int ma_audio = SOA_ACTIVE_DISABLED;
-  int ma_video = SOA_ACTIVE_DISABLED;
-  int ma_chat = SOA_ACTIVE_DISABLED;
-  int ma_image = SOA_ACTIVE_DISABLED;
-  int *p;
-
-  remote = !!remote;
+  int mode, swap;
+  int l_audio = SOA_ACTIVE_DISABLED, r_audio = SOA_ACTIVE_DISABLED;
+  int l_video = SOA_ACTIVE_DISABLED, r_video = SOA_ACTIVE_DISABLED;
+  int l_chat = SOA_ACTIVE_DISABLED,  r_chat = SOA_ACTIVE_DISABLED;
+  int l_image = SOA_ACTIVE_DISABLED, r_image = SOA_ACTIVE_DISABLED;
 
-  ma = remote ? ss->ss_remote_activity : ss->ss_local_activity;
+  int *l, *r;
 
   for (; m; m = m->m_next) {
     if (m->m_type == sdp_media_audio)
-      p = &ma_audio;
+      l = &l_audio, r = &r_audio;
     else if (m->m_type == sdp_media_video)
-      p = &ma_video;
+      l = &l_video, r = &r_video;
     else if (m->m_type == sdp_media_image)
-      p = &ma_image;
+      l = &l_image, r = &r_image;
     else if (strcasecmp(m->m_type_name, "message") == 0)
-      p = &ma_chat;
+      l = &l_chat, r = &r_chat;
     else
       continue;
 
     if (m->m_rejected) {
-      if (*p < 0)
-	*p = SOA_ACTIVE_REJECTED;
+      if (*l < 0) *l = SOA_ACTIVE_REJECTED;
+      if (*r < 0) *r = SOA_ACTIVE_REJECTED;
       continue;
     }
 
-    mode = m->m_mode;
+    mode = m->m_mode, swap = ((mode << 1) & 2) | ((mode >> 1) & 1);
 
     c = sdp_media_connections((sdp_media_t *)m);
 
-    if (remote != (c && c->c_mcast))
-      mode = ((mode << 1) & 2) | ((mode >> 1) & 1);
-
-    if (*p < 0)
-      *p = mode;
-    else
-      *p |= mode;
+    switch (activity) {
+    case soa_activity_local:
+      *l &= SOA_ACTIVE_SENDRECV;
+      *l |= c && c->c_mcast ? swap : mode;
+      break;
+    case soa_activity_remote:
+      *r &= SOA_ACTIVE_SENDRECV;
+      *r = c && c->c_mcast ? mode : swap;
+      break;
+    case soa_activity_session:
+      *l &= SOA_ACTIVE_SENDRECV;
+      *l |= c && c->c_mcast ? swap : mode;
+      *r &= SOA_ACTIVE_SENDRECV;
+      *r = c && c->c_mcast ? swap : mode;
+      break;
+    }
   }
 
-  ma->ma_audio = ma_audio;
-  ma->ma_video = ma_video;
-  ma->ma_image = ma_image;
-  ma->ma_chat = ma_chat;
+  if (activity == soa_activity_local ||
+      activity == soa_activity_session) {
+    ma = ss->ss_local_activity;
+    ma->ma_audio = l_audio;
+    ma->ma_video = l_video;
+    ma->ma_image = l_image;
+    ma->ma_chat = l_chat;
+  }
+
+  if (activity == soa_activity_remote ||
+      activity == soa_activity_session) {
+    ma = ss->ss_remote_activity;
+    ma->ma_audio = r_audio;
+    ma->ma_video = r_video;
+    ma->ma_image = r_image;
+    ma->ma_chat = r_chat;
+  }
 }
 
 /* ----------------------------------------------------------------------*/

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa_static.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa_static.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa_static.c	Sat Jan 26 14:48:14 2008
@@ -974,58 +974,28 @@
   return 0;
 }
 
-/** Check if @a session mode should be changed. */ 
-static
-int soa_sdp_mode_set_is_needed(sdp_session_t const *session,
-			       sdp_session_t const *remote,
-			       char const *hold)
-{
-  sdp_media_t const *sm, *rm, *rm_next;
-  int hold_all;
-  sdp_mode_t recv_mode;
-
-  SU_DEBUG_7(("soa_sdp_mode_set_is_needed(%p, %p, \"%s\"): called\n",
-	      (void *)session, (void *)remote, hold ? hold : ""));
-
-  if (!session )
-    return 0;
-
-  hold_all = str0cmp(hold, "*") == 0;
-
-  rm = remote ? remote->sdp_media : NULL, rm_next = NULL;
-
-  for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next) {
-    rm_next = rm ? rm->m_next : NULL;
-
-    if (sm->m_rejected)
-      continue;
-
-    if (rm) {
-      /* Mode bits do not match */
-      if (((rm->m_mode & sdp_recvonly) == sdp_recvonly)
-	  != ((sm->m_mode & sdp_sendonly) == sdp_sendonly))
-	return 1;
-    }
-
-    recv_mode = sm->m_mode & sdp_recvonly;
-    if (recv_mode && hold &&
-	(hold_all || strcasestr(hold, sm->m_type_name)))
-      return 1;
-  }
 
-  return 0;
-}
-
-
-/** Update mode within session */ 
+/** Update mode within session.
+ *
+ * @sa soatag_hold
+ *
+ * @retval 1 if session was changed (or to be changed, if @a dryrun is nonzero)
+ */ 
 static
-int soa_sdp_mode_set(sdp_session_t *session,
+int soa_sdp_mode_set(sdp_session_t const *user,
+		     int const *s2u,
+		     sdp_session_t *session,
 		     sdp_session_t const *remote,
-		     char const *hold)
+		     char const *hold,
+		     int dryrun)
 {
   sdp_media_t *sm;
-  sdp_media_t const *rm, *rm_next;
+  sdp_media_t const *rm, *rm_next, *um;
+  int retval = 0, i, j;
   int hold_all;
+  int inactive_all;
+  int inactive = 0;
+  char const *hold_media = NULL;
   sdp_mode_t send_mode, recv_mode;
 
   SU_DEBUG_7(("soa_sdp_mode_set(%p, %p, \"%s\"): called\n",
@@ -1037,25 +1007,58 @@
   rm = remote ? remote->sdp_media : NULL, rm_next = NULL;
 
   hold_all = str0cmp(hold, "*") == 0;
+  inactive_all = str0cmp(hold, "#") == 0;
+
+  i = 0;
 
-  for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next) {
+  for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next, i++) {
     rm_next = rm ? rm->m_next : NULL;
+    inactive = 0;
 
     if (sm->m_rejected)
       continue;
 
-    send_mode = sdp_sendonly;
+    assert(s2u);
+
+    for (j = 0, um = user->sdp_media; j != s2u[i]; um = um->m_next, j++)
+      assert(um);
+    assert(um);
+
+    send_mode = um->m_mode & sdp_sendonly;
     if (rm)
       send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0;
 
-    recv_mode = sm->m_mode & sdp_recvonly;
-    if (recv_mode && hold && (hold_all || strcasestr(hold, sm->m_type_name)))
+    recv_mode = um->m_mode & sdp_recvonly;
+
+    if (rm && rm->m_mode == sdp_inactive) {
+      send_mode = recv_mode = 0;
+    }
+    else if (inactive_all) {
+      send_mode = recv_mode = 0;
+    }
+    else if (hold_all) {
       recv_mode = 0;
+    }
+    else if (hold && (hold_media = strcasestr(hold, sm->m_type_name))) {
+      recv_mode = 0;
+      hold_media += strlen(sm->m_type_name);
+      hold_media += strspn(hold_media, " \t");
+      if (hold_media[0] == '=') {
+	hold_media += strspn(hold, " \t");
+	if (strncasecmp(hold_media, "inactive", strlen("inactive")) == 0)
+	  recv_mode = send_mode = 0;
+      }
+    }
+
+    if (sm->m_mode != (unsigned)(recv_mode | send_mode))
+      retval = 1;
 
-    sm->m_mode = recv_mode | send_mode;
+    if (!dryrun) {
+      sm->m_mode = recv_mode | send_mode;
+    }
   }
 
-  return 0;
+  return retval;
 }
 
 enum offer_answer_action {
@@ -1213,16 +1216,22 @@
 
   /* Step D: Set media mode bits */
   switch (action) {
+    int const *s2u_;
+
   case generate_offer:
   case generate_answer:
   case process_answer:
-    if (soa_sdp_mode_set_is_needed(local, remote, ss->ss_hold)) {
+    s2u_ = s2u;
+
+    if (!s2u_) s2u_ = sss->sss_s2u;
+
+    if (soa_sdp_mode_set(user, s2u_, local, remote, ss->ss_hold, 1)) {
       if (local != local0) {
 	*local0 = *local, local = local0;
 	DUP_LOCAL(local);
       }
 
-      soa_sdp_mode_set(local, remote, ss->ss_hold);
+      soa_sdp_mode_set(user, s2u_, local, remote, ss->ss_hold, 0);
     }
     break;
   default:

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa_tag.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa_tag.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/soa_tag.c	Sat Jan 26 14:48:14 2008
@@ -585,12 +585,22 @@
 
 /**@def SOATAG_HOLD(x)
  *
- * Hold media stream or streams. When putting a SIP session on hold, the
- * application can include, e.g., SOATAG_HOLD("audio") or
- * SOATAG_HOLD("video") or SOATAG_HOLD("audio, video") or SOATAG_HOLD("*")
- * as @soa parameters. When resuming the session, it can include
- * SOATAG_HOLD(NULL). Note that last SOATAG_HOLD() in the tag list will
- * override the SOATAG_HOLD() tags before it.
+ * Hold media stream or streams. 
+ *
+ * The hold media stream will have the attribute a=sendonly (meaning that
+ * some hold announcements or pause music is sent to the held party but that
+ * the held party should not generate any media) or a=inactive (meaning that
+ * no media is sent). 
+ *
+ * When putting a SIP session on hold with sendonly, the application can
+ * include, e.g., SOATAG_HOLD("audio") or SOATAG_HOLD("video") or
+ * SOATAG_HOLD("audio, video") or SOATAG_HOLD("*") as @soa parameters. When
+ * using inactive instead, the application should use "#" or
+ * "audio=inactive" instead. When resuming the session, application should
+ * include the tag SOATAG_HOLD(NULL).
+ *
+ * Note that last SOATAG_HOLD() in the tag list will override the
+ * SOATAG_HOLD() tags before it.
  *
  * @par Used with
  *    soa_set_params(), soa_get_params(), soa_get_paramlist() \n

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/sofia-sip/soa_session.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/sofia-sip/soa_session.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/sofia-sip/soa_session.h	Sat Jan 26 14:48:14 2008
@@ -238,8 +238,11 @@
 SOFIAPUBFUN int soa_set_status(soa_session_t *ss,
 			       int status, char const *phrase);
 
+enum soa_activity { soa_activity_local, soa_activity_remote, soa_activity_session };
+
 SOFIAPUBFUN void soa_set_activity(soa_session_t *ss, 
-				  sdp_media_t const *m, int remote);
+				  sdp_media_t const *m, 
+				  enum soa_activity activity);
 
 SOFIAPUBFUN int soa_description_set(soa_session_t *ss, 
 				    struct soa_description *ssd,

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/test_soa.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/test_soa.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/soa/test_soa.c	Sat Jan 26 14:48:14 2008
@@ -451,20 +451,67 @@
   TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDONLY);
   TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDONLY);
 
+  /* 'A' will put call inactive */
+  offer = NONE;
+  TEST(soa_set_params(a, SOATAG_HOLD("#"), TAG_END()), 1);
+
+  TEST(soa_generate_offer(a, 1, test_completed), 0);
+  TEST(soa_get_local_sdp(a, NULL, &offer, &offerlen), 1);
+  TEST_1(offer != NULL && offer != NONE);
+  TEST_1(strstr(offer, "a=inactive"));
+  TEST(soa_set_remote_sdp(b, 0, offer, offerlen), 1);
+  TEST(soa_generate_answer(b, test_completed), 0);
+  TEST_1(soa_is_complete(b));
+  TEST(soa_activate(b, NULL), 0);
+  TEST(soa_get_local_sdp(b, NULL, &answer, &answerlen), 1);
+  TEST_1(answer != NULL && answer != NONE);
+  TEST_1(strstr(answer, "a=inactive"));
+  TEST(soa_set_remote_sdp(a, 0, answer, -1), 1);
+  TEST(soa_process_answer(a, test_completed), 0);
+  TEST(soa_activate(a, NULL), 0);
+
+  TEST(soa_is_audio_active(a), SOA_ACTIVE_INACTIVE);
+  TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_INACTIVE);
+
+  /* B will send an offer to A, but there is no change in O/A status */
+  TEST(soa_generate_offer(b, 1, test_completed), 0);
+  TEST(soa_get_local_sdp(b, NULL, &offer, &offerlen), 1);
+  TEST_1(offer != NULL && offer != NONE);
+  TEST_1(!strstr(offer, "a=inactive"));
+  printf("offer:\n%s", offer);
+  TEST(soa_set_remote_sdp(a, 0, offer, offerlen), 1);
+  TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
+  TEST(soa_generate_answer(a, test_completed), 0);
+  TEST(soa_is_audio_active(a), SOA_ACTIVE_INACTIVE);
+  TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_INACTIVE);
+  TEST_1(soa_is_complete(a));
+  TEST(soa_activate(a, NULL), 0);
+  TEST(soa_get_local_sdp(a, NULL, &answer, &answerlen), 1);
+  TEST_1(answer != NULL && answer != NONE);
+  TEST_1(strstr(answer, "a=inactive"));
+  printf("answer:\n%s", answer);
+  TEST(soa_set_remote_sdp(b, 0, answer, -1), 1);
+  TEST(soa_process_answer(b, test_completed), 0);
+  TEST(soa_activate(b, NULL), 0);
+
+
+  TEST(soa_is_audio_active(b), SOA_ACTIVE_INACTIVE);
+  TEST(soa_is_remote_audio_active(b), SOA_ACTIVE_INACTIVE);
+
   /* 'A' will release hold. */ 
   TEST(soa_set_params(a, SOATAG_HOLD(NULL), TAG_END()), 1);
 
   TEST(soa_generate_offer(a, 1, test_completed), 0);
   TEST(soa_get_local_sdp(a, NULL, &offer, &offerlen), 1);
   TEST_1(offer != NULL && offer != NONE);
-  TEST_1(!strstr(offer, "a=sendonly"));
+  TEST_1(!strstr(offer, "a=sendonly") && !strstr(offer, "a=inactive"));
   TEST(soa_set_remote_sdp(b, 0, offer, offerlen), 1);
   TEST(soa_generate_answer(b, test_completed), 0);
   TEST_1(soa_is_complete(b));
   TEST(soa_activate(b, NULL), 0);
   TEST(soa_get_local_sdp(b, NULL, &answer, &answerlen), 1);
   TEST_1(answer != NULL && answer != NONE);
-  TEST_1(!strstr(answer, "a=recvonly"));
+  TEST_1(!strstr(answer, "a=recvonly") && !strstr(answer, "a=inactive"));
   TEST(soa_set_remote_sdp(a, 0, answer, -1), 1);
   TEST(soa_process_answer(a, test_completed), 0);
   TEST(soa_activate(a, NULL), 0);
@@ -1329,7 +1376,7 @@
 {
   BEGIN();
 
-#if 0
+#if 0				/* This has never been implemented */
   int n;
   
   char const *caps = NONE, *offer = NONE, *answer = NONE;

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sofia-resolv/sres.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sofia-resolv/sres.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sofia-resolv/sres.h	Sat Jan 26 14:48:14 2008
@@ -218,21 +218,13 @@
                                              uint16_t type,
 					     struct sockaddr const *addr);
 
-/**Modify the priority of the specified SRV records.
- * 
- * @param res       pointer to resolver object
- * @param service   domain name of the SRV records to search in cache
- * @param target    target to lower the prio
- * @param port      port number to lower the prio
- * @param newprio   new priority value
- *
- * @return Number of modified records on success, -1 otherwise
- */
+/**Modify the priority of the specified SRV records. */
 SRESPUBFUN
 int sres_set_cached_srv_priority(sres_resolver_t *res,
 				 char const *domain,
 				 char const *target,
 				 uint16_t port,
+				 uint32_t newttl,
 				 uint16_t newprio);
 
 

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sofia-resolv/sres_cache.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sofia-resolv/sres_cache.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sofia-resolv/sres_cache.h	Sat Jan 26 14:48:14 2008
@@ -107,7 +107,8 @@
 					   char const *domain,
 					   char const *target,
 					   uint16_t port,
-					   uint16_t prio);
+					   uint32_t newttl,
+					   uint16_t newprio);
 
 #ifdef __cplusplus
 }

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c	Sat Jan 26 14:48:14 2008
@@ -1358,6 +1358,7 @@
  * @param target   SRV target of the SRV record(s) to modify
  * @param port     port number of SRV record(s) to modify 
  *                 (in host byte order) 
+ * @param ttl      new ttl for SRV records of the domain
  * @param priority new priority value (0=highest, 65535=lowest)
  *
  * @sa sres_cache_set_srv_priority()
@@ -1368,6 +1369,7 @@
 				 char const *domain,
 				 char const *target,
 				 uint16_t port,
+				 uint32_t ttl,
 				 uint16_t priority)
 {
   char rooted_domain[SRES_MAXDNAME];
@@ -1381,7 +1383,8 @@
     return -1;
 
   return sres_cache_set_srv_priority(res->res_cache, 
-				     domain, target, port, priority);
+				     domain, target, port, 
+				     ttl, priority);
 }
 
 

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c	Sat Jan 26 14:48:14 2008
@@ -483,6 +483,7 @@
  * @param target   SRV target of the SRV record(s) to modify
  * @param port     port number of SRV record(s) to modify 
  *                 (in host byte order) 
+ * @param ttl      new ttl
  * @param priority new priority value (0=highest, 65535=lowest)
  *
  * @sa sres_set_cached_srv_priority()
@@ -493,12 +494,14 @@
 				char const *domain,
 				char const *target,
 				uint16_t port,
+				uint32_t ttl,
 				uint16_t priority)
 {
   int ret = 0;
   unsigned hash;
   sres_rr_hash_entry_t **iter;
-
+  time_t expires;
+  
   if (cache == NULL || domain == NULL || target == NULL)
     return -1;
 
@@ -507,6 +510,9 @@
   if (!LOCK(cache))
     return -1;
 
+  time(&expires);
+  expires += ttl;
+
   for (iter = sres_htable_hash(cache->cache_hash, hash);
        iter && *iter;
        iter = sres_htable_next(cache->cache_hash, iter)) {
@@ -514,13 +520,17 @@
     
     if (rr && rr->sr_name &&
 	sres_type_srv == rr->sr_type &&
-	(port == 0 || rr->sr_srv->srv_port == port) &&
-	rr->sr_srv->srv_target &&
-	strcasecmp(rr->sr_srv->srv_target, target) == 0 &&
 	strcasecmp(rr->sr_name, domain) == 0) {
-      /* record found --> change priority of server */
-      rr->sr_srv->srv_priority = priority;
-      ret++;
+
+      (*iter)->rr_expires = expires;
+      
+      if ((port == 0 || rr->sr_srv->srv_port == port) &&
+	  rr->sr_srv->srv_target &&
+	  strcasecmp(rr->sr_srv->srv_target, target) == 0) {
+	/* record found --> change priority of server */
+	rr->sr_srv->srv_priority = priority;
+	ret++;
+      }
     }
   }
 

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_addrinfo.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_addrinfo.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_addrinfo.h	Sat Jan 26 14:48:14 2008
@@ -126,7 +126,7 @@
 #define	AI_MASK		(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
 #endif
 
-/** RFC 1576 address info structure. */
+/** @RFC1576 address info structure. */
 typedef struct addrinfo su_addrinfo_t;
 
 /** Translate address and service. */

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_addrinfo.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_addrinfo.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_addrinfo.c	Sat Jan 26 14:48:14 2008
@@ -893,6 +893,7 @@
 {
   int retval;
   su_addrinfo_t *ai;
+  char const *realservice = service;
 
   if (!service || service[0] == '\0')
     service = "0";
@@ -932,6 +933,9 @@
 
   retval = getaddrinfo(node, service, hints, res);
 
+  if (service != realservice && retval == EAI_SERVICE)
+    retval = getaddrinfo(node, realservice, hints, res);
+
   if (retval == 0) {
     for (ai = *res; ai; ai = ai->ai_next) {
       if (ai->ai_protocol)



More information about the Freeswitch-svn mailing list