From 74740cca5f21911edadabb4d2795d28743c099da Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Fri, 28 Jun 2013 10:42:01 -0500
Subject: [PATCH] FS-5527 --resolve

Conflicts:
	libs/sofia-sip/.update
	libs/sofia-sip/libsofia-sip-ua/nta/nta.c
---
 libs/sofia-sip/.update                        |  1 -
 libs/sofia-sip/libsofia-sip-ua/nta/nta.c      | 45 ++++++++++---------
 .../libsofia-sip-ua/su/sofia-sip/su_time.h    |  7 ++-
 libs/sofia-sip/libsofia-sip-ua/su/su_time0.c  | 14 ++++++
 src/mod/endpoints/mod_sofia/sofia.c           | 19 ++++++++
 5 files changed, 64 insertions(+), 22 deletions(-)

diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update
index 3cdde5d830..e69de29bb2 100644
--- a/libs/sofia-sip/.update
+++ b/libs/sofia-sip/.update
@@ -1 +0,0 @@
-Thu Jun 20 10:51:51 CDT 2013
diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
index 3fe081f429..86355a5f45 100644
--- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
+++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
@@ -149,9 +149,7 @@ struct nta_agent_s
   nta_update_magic_t   *sa_update_magic;
   nta_update_tport_f   *sa_update_tport;
 
-  su_time_t             sa_now;	 /**< Timestamp in microsecond resolution. */
   uint32_t              sa_next; /**< Timestamp for next agent_timer. */
-  uint32_t              sa_millisec; /**< Timestamp in milliseconds. */
 
   msg_mclass_t const   *sa_mclass;
   uint32_t sa_flags;		/**< SIP message flags */
@@ -1237,15 +1235,12 @@ void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent)
 
   agent->sa_next = 0;
 
-  agent->sa_now = stamp;
-  agent->sa_millisec = now;
   agent->sa_in_timer = 1;
 
+
   _nta_outgoing_timer(agent);
   _nta_incoming_timer(agent);
 
-  /* agent->sa_now is used only if sa_millisec != 0 */
-  agent->sa_millisec = 0;
   agent->sa_in_timer = 0;
 
   /* Calculate next timeout */
@@ -1330,12 +1325,12 @@ uint32_t set_timeout(nta_agent_t *agent, uint32_t offset)
   if (offset == 0)
     return 0;
 
-  if (agent->sa_millisec) /* Avoid expensive call to su_now() */
-    now = agent->sa_now, ms = agent->sa_millisec;
-  else
-    now = su_now(), ms = su_time_ms(now);
+  now = su_now();
+  ms = su_time_ms(now);
 
-  next = ms + offset; if (next == 0) next = 1;
+  next = ms + offset;
+
+  if (next == 0) next = 1;
 
   if (agent->sa_in_timer)	/* Currently executing timer */
     return next;
@@ -1360,9 +1355,6 @@ uint32_t set_timeout(nta_agent_t *agent, uint32_t offset)
 static
 su_time_t agent_now(nta_agent_t const *agent)
 {
-  if (agent && agent->sa_millisec != 0)
-    return agent->sa_now;
-  else
     return su_now();
 }
 
@@ -2764,8 +2756,6 @@ void agent_recv_message(nta_agent_t *agent,
 {
   sip_t *sip = sip_object(msg);
 
-  agent->sa_millisec = su_time_ms(agent->sa_now = now);
-
   if (sip && sip->sip_request) {
     agent_recv_request(agent, msg, sip, tport);
   }
@@ -2775,8 +2765,6 @@ void agent_recv_message(nta_agent_t *agent,
   else {
     agent_recv_garbage(agent, msg, tport);
   }
-
-  agent->sa_millisec = 0;
 }
 
 /** @internal Handle incoming requests. */
@@ -6849,7 +6837,7 @@ enum {
 static void
 _nta_incoming_timer(nta_agent_t *sa)
 {
-  uint32_t now = sa->sa_millisec;
+  uint32_t now = su_time_ms(su_now());
   nta_incoming_t *irq, *irq_next;
   size_t retransmitted = 0, timeout = 0, terminated = 0, destroyed = 0;
   size_t unconfirmed =
@@ -6866,6 +6854,9 @@ _nta_incoming_timer(nta_agent_t *sa)
 
   /* Handle retry queue */
   while ((irq = sa->sa_in.re_list)) {
+
+	  now = su_time_ms(su_now());
+
     if ((int32_t)(irq->irq_retry - now) > 0)
       break;
     if (retransmitted >= timer_max_retransmit)
@@ -6923,6 +6914,8 @@ _nta_incoming_timer(nta_agent_t *sa)
   }
 
   while ((irq = sa->sa_in.final_failed->q_head)) {
+	  
+
     incoming_remove(irq);
     irq->irq_final_failed = 0;
 
@@ -6954,6 +6947,8 @@ _nta_incoming_timer(nta_agent_t *sa)
     assert(irq->irq_status < 200);
     assert(irq->irq_timeout);
 
+	now = su_time_ms(su_now());
+
     if ((int32_t)(irq->irq_timeout - now) > 0)
       break;
     if (timeout >= timer_max_timeout)
@@ -6974,6 +6969,8 @@ _nta_incoming_timer(nta_agent_t *sa)
     assert(irq->irq_timeout);
     assert(irq->irq_method == sip_method_invite);
 
+	now = su_time_ms(su_now());
+
     if ((int32_t)(irq->irq_timeout - now) > 0 ||
 	timeout >= timer_max_timeout ||
 	terminated >= timer_max_terminate)
@@ -7002,6 +6999,8 @@ _nta_incoming_timer(nta_agent_t *sa)
     assert(irq->irq_status >= 200);
     assert(irq->irq_method == sip_method_invite);
 
+	now = su_time_ms(su_now());
+
     if ((int32_t)(irq->irq_timeout - now) > 0 ||
 	terminated >= timer_max_terminate)
       break;
@@ -7024,6 +7023,8 @@ _nta_incoming_timer(nta_agent_t *sa)
     assert(irq->irq_timeout);
     assert(irq->irq_method != sip_method_invite);
 
+	now = su_time_ms(su_now());	
+
     if ((int32_t)(irq->irq_timeout - now) > 0 ||
 	terminated >= timer_max_terminate)
       break;
@@ -7043,6 +7044,7 @@ _nta_incoming_timer(nta_agent_t *sa)
   }
 
   for (irq = sa->sa_in.terminated->q_head; irq; irq = irq_next) {
+	  
     irq_next = irq->irq_next;
     if (irq->irq_destroyed)
       incoming_free_queue(rq, irq);
@@ -8699,7 +8701,7 @@ void outgoing_destroy(nta_outgoing_t *orq)
 static void
 _nta_outgoing_timer(nta_agent_t *sa)
 {
-  uint32_t now = sa->sa_millisec;
+  uint32_t now = su_time_ms(su_now());
   nta_outgoing_t *orq;
   outgoing_queue_t rq[1];
   size_t retransmitted = 0, terminated = 0, timeout = 0, destroyed;
@@ -8713,6 +8715,9 @@ _nta_outgoing_timer(nta_agent_t *sa)
   outgoing_queue_init(sa->sa_out.free = rq, 0);
 
   while ((orq = sa->sa_out.re_list)) {
+
+	  now = su_time_ms(su_now());
+
     if ((int32_t)(orq->orq_retry - now) > 0)
       break;
     if (retransmitted >= timer_max_retransmit)
diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_time.h b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_time.h
index b4acba6a7d..ea347e80a0 100644
--- a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_time.h
+++ b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_time.h
@@ -85,6 +85,11 @@ typedef uint64_t su_nanotime_t;
 
 #define SU_E9 (1000000000U)
 
+typedef void (*su_time_func_t)(su_time_t *tv);
+
+
+SOFIAPUBFUN void su_set_time_func(su_time_func_t func);
+
 SOFIAPUBFUN su_nanotime_t su_nanotime(su_nanotime_t *return_time);
 SOFIAPUBFUN su_nanotime_t su_monotime(su_nanotime_t *return_time);
 
@@ -138,7 +143,7 @@ su_inline uint32_t su_ntp_fraq(su_time_t t)
 /** Time as milliseconds. */
 su_inline uint32_t su_time_ms(su_time_t t)
 {
-  return t.tv_sec * 1000 + (t.tv_usec + 500) / 1000;
+	return (t.tv_sec * 1000) + ((t.tv_usec + 500) / 1000);
 }
 #endif
 
diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_time0.c b/libs/sofia-sip/libsofia-sip-ua/su/su_time0.c
index 0543e45aa0..7267213156 100644
--- a/libs/sofia-sip/libsofia-sip-ua/su/su_time0.c
+++ b/libs/sofia-sip/libsofia-sip-ua/su/su_time0.c
@@ -69,6 +69,13 @@
 void (*_su_time)(su_time_t *tv);
 uint64_t (*_su_nanotime)(uint64_t *);
 
+static su_time_func_t custom_time_func = NULL;
+
+void su_set_time_func(su_time_func_t func) {
+	custom_time_func = func;
+}
+
+
 /** Get current time.
  *
  * The function @c su_time() fills its argument with the current NTP
@@ -79,6 +86,13 @@ uint64_t (*_su_nanotime)(uint64_t *);
 void su_time(su_time_t *tv)
 {
 	su_time_t ltv = {0,0};
+
+	if (custom_time_func) {
+		custom_time_func(&ltv);
+		if (tv) *tv = ltv;
+		return;
+	}
+
 #if HAVE_CLOCK_GETTIME
 	struct timespec ctv = {0};
 	if (clock_gettime(CLOCK_REALTIME, &ctv) == 0) {
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 157092a005..8095a83c31 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -3434,6 +3434,21 @@ static void config_sofia_profile_urls(sofia_profile_t * profile)
 	}
 }
 
+#ifdef SOFIA_CUSTOM_TIME
+/* appears to not be granular enough */
+static void sofia_time(su_time_t *tv)
+{
+	switch_time_t now;
+
+	if (tv) {
+		now = switch_micro_time_now();
+		tv->tv_sec = ((uint32_t) (now / 1000000)) + 2208988800UL;
+		tv->tv_usec = (uint32_t) (now % 1000000);
+	}
+	
+}
+#endif
+
 switch_status_t sofia_init(void)
 {
 	su_init();
@@ -3442,6 +3457,10 @@ switch_status_t sofia_init(void)
 		return SWITCH_STATUS_GENERR;
 	}
 
+#ifdef SOFIA_TIME
+	su_set_time_func(sofia_time);
+#endif
+
 	/* Redirect loggers in sofia */
 	su_log_redirect(su_log_default, logger, NULL);
 	su_log_redirect(tport_log, logger, NULL);