Freeswitch-svn
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- 12151 discussions
[commit] r11853 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua-glib/su-glib libsofia-sip-ua/su libsofia-sip-ua/su/sofia-sip
by FreeSWITCH SVN 11 Feb '09
by FreeSWITCH SVN 11 Feb '09
11 Feb '09
Author: mikej
Date: Wed Feb 11 11:17:49 2009
New Revision: 11853
Log:
Wed Jan 28 12:07:02 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* su: added API functions su_timer_is_set() and su_timer_latest()
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Wed Feb 11 11:17:49 2009
@@ -1 +1 @@
-Wed Feb 11 11:16:35 CST 2009
+Wed Feb 11 11:17:39 CST 2009
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source.c Wed Feb 11 11:17:49 2009
@@ -97,8 +97,6 @@
static void su_source_decref(su_port_t *self, int blocking, char const *who);
static struct _GSource *su_source_gsource(su_port_t *port);
-static int su_source_send(su_port_t *self, su_msg_r rmsg);
-
static int su_source_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
@@ -126,6 +124,8 @@
static int su_source_remove_prepoll(su_port_t *port,
su_root_t *root);
static int su_source_multishot(su_port_t *self, int multishot);
+static int su_source_wakeup(su_port_t *self);
+static int su_source_is_running(su_port_t *self);
static char const *su_source_name(su_port_t const *self);
@@ -141,7 +141,7 @@
su_source_gsource,
- su_source_send,
+ su_base_port_send,
su_source_register,
su_source_unregister,
su_source_deregister,
@@ -162,6 +162,10 @@
su_base_port_start_shared,
su_base_port_wait,
NULL,
+ su_base_port_deferrable,
+ su_base_port_max_defer,
+ su_source_wakeup,
+ su_source_is_running,
}};
static char const *su_source_name(su_port_t const *self)
@@ -308,37 +312,10 @@
su_source_port_deinit(ss->ss_port);
}
-void su_source_port_lock(su_port_t *self, char const *who)
-{
- PORT_LOCK_DEBUG(("%p at %s locking(%p)...",
- (void *)g_thread_self(), who, self));
-
- g_static_mutex_lock(self->sup_mutex);
-
- PORT_LOCK_DEBUG((" ...%p at %s locked(%p)...",
- (void *)g_thread_self(), who, self));
-}
-
-void su_source_port_unlock(su_port_t *self, char const *who)
-{
- g_static_mutex_unlock(self->sup_mutex);
-
- PORT_LOCK_DEBUG((" ...%p at %s unlocked(%p)\n",
- (void *)g_thread_self(), who, self));
-}
-
/** @internal Send a message to the port. */
-int su_source_send(su_port_t *self, su_msg_r rmsg)
+int su_source_wakeup(su_port_t *self)
{
- int wakeup = su_base_port_send(self, rmsg);
- GMainContext *gmc;
-
- if (wakeup < 0)
- return -1;
- if (wakeup == 0)
- return 0;
-
- gmc = g_source_get_context(self->sup_source);
+ GMainContext *gmc = g_source_get_context(self->sup_source);
if (gmc)
g_main_context_wakeup(gmc);
@@ -837,7 +814,7 @@
* @return Number of wait objects removed.
*/
int su_source_unregister_all(su_port_t *self,
- su_root_t *root)
+ su_root_t *root)
{
unsigned i, j;
unsigned n_waits;
@@ -881,8 +858,7 @@
/**Set mask for a registered event. @internal
*
- * The function su_source_eventmask() sets the mask describing events that can
- * signal the registered callback.
+ * Sets the mask describing events that can signal the registered callback.
*
* @param port pointer to port object
* @param index registration index
@@ -892,6 +868,7 @@
* @retval 0 when successful,
* @retval -1 upon an error.
*/
+static
int su_source_eventmask(su_port_t *self, int index, int socket, int events)
{
unsigned n;
@@ -932,15 +909,13 @@
}
-/** @internal Main loop.
- *
- * The function @c su_source_run() runs the main loop
+/** @internal Run the main loop.
*
- * The function @c su_source_run() runs until @c su_source_break() is called
- * from a callback.
+ * The main loop runs until su_source_break() is called from a callback.
*
- * @param self pointer to root object
+ * @param self pointer to port object
* */
+static
void su_source_run(su_port_t *self)
{
GMainContext *gmc;
@@ -959,6 +934,11 @@
}
}
+static int su_source_is_running(su_port_t *self)
+{
+ return self->sup_main_loop && g_main_loop_is_running(self->sup_main_loop);
+}
+
/** @internal
* The function @c su_source_break() is used to terminate execution of @c
* su_source_run(). It can be called from a callback function.
@@ -966,6 +946,7 @@
* @param self pointer to port
*
*/
+static
void su_source_break(su_port_t *self)
{
enter;
@@ -1112,4 +1093,3 @@
{
su_port_prefer(su_source_port_create, NULL);
}
-
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h Wed Feb 11 11:17:49 2009
@@ -491,6 +491,8 @@
SOFIAPUBFUN su_timer_t *su_timer_create(su_task_r const, su_duration_t msec)
__attribute__((__malloc__));
SOFIAPUBFUN void su_timer_destroy(su_timer_t *);
+SOFIAPUBFUN int su_timer_is_set(su_timer_t const *t); /* 1.12.11 */
+SOFIAPUBFUN su_time_t su_timer_latest(su_timer_t const *t);
SOFIAPUBFUN int su_timer_set(su_timer_t *, su_timer_f, su_timer_arg_t *);
SOFIAPUBFUN int su_timer_set_interval(su_timer_t *t, su_timer_f,
su_timer_arg_t *, su_duration_t);
@@ -506,7 +508,7 @@
SOFIAPUBFUN int su_timer_expire(su_timer_queue_t * const,
su_duration_t *tout,
su_time_t now);
-SOFIAPUBFUN int su_timer_deferrable(su_timer_t *t, int value);
+SOFIAPUBFUN int su_timer_deferrable(su_timer_t *t, int value); /* 1.12.11 */
/* Tasks */
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c Wed Feb 11 11:17:49 2009
@@ -157,12 +157,11 @@
struct su_timer_s {
su_task_r sut_task; /**< Task reference */
- size_t sut_heap_index; /**< Timer is set (inserted in heap) */
+ size_t sut_set; /**< Timer is set (inserted in heap) */
su_time_t sut_when; /**< When timer should be waken up next time */
su_duration_t sut_duration; /**< Timer duration */
su_timer_f sut_wakeup; /**< Function to call when waken up */
su_timer_arg_t *sut_arg; /**< Pointer to argument data */
- su_time_t sut_run; /**< When this timer was last waken up */
unsigned sut_woken; /**< Timer has waken up this many times */
unsigned sut_running:2;/**< Timer is running */
@@ -176,13 +175,13 @@
run_for_ever = 2 /**< Do not compensate */
};
-#define SU_TIMER_IS_SET(sut) ((sut)->sut_heap_index != 0)
+#define SU_TIMER_IS_SET(sut) ((sut)->sut_set != 0)
HEAP_DECLARE(su_inline, su_timer_queue_t, timers_, su_timer_t *);
su_inline void timers_set(su_timer_t **array, size_t index, su_timer_t *t)
{
- array[t->sut_heap_index = index] = t;
+ array[t->sut_set = index] = t;
}
su_inline int timers_less(su_timer_t *a, su_timer_t *b)
@@ -224,7 +223,7 @@
return -1;
if (SU_TIMER_IS_SET(t))
- timers_remove(timers[0], t->sut_heap_index);
+ timers_remove(timers[0], t->sut_set);
t->sut_wakeup = wakeup;
t->sut_arg = arg;
@@ -328,6 +327,37 @@
}
}
+/** Check if the timer has been set.
+ *
+ * @param t pointer to a timer object
+ *
+ * @return Nonzero if set, zero if reset.
+ *
+ * @NEW_1_12_11
+ */
+int su_timer_is_set(su_timer_t const *t)
+{
+ return t && t->sut_set != 0;
+}
+
+/**Return when the timer has been last expired.
+ *
+ * @param t pointer to a timer object
+ *
+ * @return Timestamp (as returned by su_time()).
+ *
+ * @note If the timer is running (set with su_timer_run()), the returned
+ * timestamp not the actual time but it is rather calculated from the
+ * initial timestamp.
+ *
+ * @NEW_1_12_11
+ */
+su_time_t su_timer_latest(su_timer_t const *t)
+{
+ su_time_t tv = { 0, 0 };
+
+ return t ? t->sut_when : tv;
+}
/** Set the timer for the given @a interval.
*
@@ -415,16 +445,14 @@
su_timer_arg_t *arg)
{
su_timer_queue_t *timers = su_timer_queue(t, 1, "su_timer_run");
- su_time_t now;
if (timers == NULL)
return -1;
t->sut_running = run_at_intervals;
- t->sut_run = now = su_now();
t->sut_woken = 0;
- return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
+ return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
}
/**Set the timer for regular intervals.
@@ -448,16 +476,14 @@
su_timer_arg_t *arg)
{
su_timer_queue_t *timers = su_timer_queue(t, 1, "su_timer_set_for_ever");
- su_time_t now;
if (timers == NULL)
return -1;
t->sut_running = run_for_ever;
- t->sut_run = now = su_now();
t->sut_woken = 0;
- return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
+ return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
}
/**Reset the timer.
@@ -476,14 +502,12 @@
return -1;
if (SU_TIMER_IS_SET(t))
- timers_remove(timers[0], t->sut_heap_index);
+ timers_remove(timers[0], t->sut_set);
t->sut_wakeup = NULL;
t->sut_arg = NULL;
t->sut_running = reset;
- memset(&t->sut_run, 0, sizeof(t->sut_run));
-
return 0;
}
@@ -528,12 +552,13 @@
if (t->sut_running == run_at_intervals) {
while (t->sut_running == run_at_intervals &&
+ t->sut_set == 0 &&
t->sut_duration > 0) {
if (su_time_diff(t->sut_when, now) > 0) {
- su_timer_set0(timers, t, f, t->sut_arg, t->sut_run, 0);
+ su_timer_set0(timers, t, f, t->sut_arg, t->sut_when, 0);
break;
}
- t->sut_when = t->sut_run = su_time_add(t->sut_run, t->sut_duration);
+ t->sut_when = su_time_add(t->sut_when, t->sut_duration);
t->sut_woken++;
f(su_root_magic(su_task_root(t->sut_task)), t, t->sut_arg), n++;
}
@@ -542,7 +567,7 @@
t->sut_woken++;
t->sut_when = now;
f(su_root_magic(su_task_root(t->sut_task)), t, t->sut_arg), n++;
- if (t->sut_running == run_for_ever)
+ if (t->sut_running == run_for_ever && t->sut_set == 0)
su_timer_set0(timers, t, f, t->sut_arg, now, t->sut_duration);
}
else {
1
0
[commit] r11852 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/su libsofia-sip-ua/su/sofia-sip
by FreeSWITCH SVN 11 Feb '09
by FreeSWITCH SVN 11 Feb '09
11 Feb '09
Author: mikej
Date: Wed Feb 11 11:16:44 2009
New Revision: 11852
Log:
Wed Jan 28 12:06:06 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* sofia-sip/su_wait.h: added su_timer_deferrable(), su_task_wakeup(), su_root_set_max_defer(), su_root_get_max_defer() and su_task_deferrable().
Added implementation to different main-loop implementations in
libsofia-sip-ua/su.
Fixed su_task_is_running().
In libsofia-sip-ua/su, added tests for deferred timers.
In libsofia-sip-ua-glib/su-glib/su_source.c, added su_source_wakeup() and
su_source_is_running(). Using su_base_port_send() instead of
su_source_send(). Using su_base_port_deferable() and
su_base_port_max_defer(), too.
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_devpoll_port.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_epoll_port.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_kqueue_port.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_osx_runloop.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_poll_port.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_port.h
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_root.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_select_port.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_socket_port.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_win32_port.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Wed Feb 11 11:16:44 2009
@@ -1 +1 @@
-Wed Feb 11 11:15:57 CST 2009
+Wed Feb 11 11:16:35 CST 2009
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h Wed Feb 11 11:16:44 2009
@@ -484,6 +484,9 @@
SOFIAPUBFUN int su_root_obtain(su_root_t *root);
SOFIAPUBFUN int su_root_has_thread(su_root_t *root);
+SOFIAPUBFUN int su_root_set_max_defer(su_root_t *, su_duration_t max_defer);
+SOFIAPUBFUN su_duration_t su_root_get_max_defer(su_root_t const *self);
+
/* Timers */
SOFIAPUBFUN su_timer_t *su_timer_create(su_task_r const, su_duration_t msec)
__attribute__((__malloc__));
@@ -503,10 +506,10 @@
SOFIAPUBFUN int su_timer_expire(su_timer_queue_t * const,
su_duration_t *tout,
su_time_t now);
+SOFIAPUBFUN int su_timer_deferrable(su_timer_t *t, int value);
/* Tasks */
-/** NULL task. */
SOFIAPUBVAR su_task_r const su_task_null;
SOFIAPUBFUN _su_task_r su_task_init(su_task_r task);
@@ -519,6 +522,9 @@
SOFIAPUBFUN su_root_t *su_task_root(su_task_r const self);
SOFIAPUBFUN su_timer_queue_t *su_task_timers(su_task_r const self);
+SOFIAPUBFUN su_timer_queue_t *su_task_deferrable(su_task_r const task);
+
+SOFIAPUBFUN int su_task_wakeup(su_task_r const task);
SOFIAPUBFUN int su_task_execute(su_task_r const task,
int (*function)(void *), void *arg,
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c Wed Feb 11 11:16:44 2009
@@ -73,6 +73,8 @@
if (self) {
self->sup_vtable = vtable;
self->sup_tail = &self->sup_head;
+ self->sup_max_defer = 15 * 1000;
+
return su_port_obtain(self);
}
@@ -149,7 +151,6 @@
/** @internal Send a message to the port.
*
- * @retval 1 if port thread needs to be woken
* @retval 0 if there are other messages in queue, too
* @retval -1 upon an error
*/
@@ -167,7 +168,10 @@
su_port_unlock(self, "su_port_send");
- return wakeup;
+ if (wakeup > 0)
+ su_port_wakeup(self);
+
+ return 0;
}
else {
su_msg_destroy(rmsg);
@@ -317,12 +321,12 @@
*/
void su_base_port_run(su_port_t *self)
{
- su_duration_t tout = 0;
+ su_duration_t tout = 0, tout2 = 0;
assert(su_port_own_thread(self));
for (self->sup_running = 1; self->sup_running;) {
- tout = 2000;
+ tout = self->sup_max_defer;
if (self->sup_prepoll)
self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);
@@ -330,8 +334,11 @@
if (self->sup_head)
self->sup_vtable->su_port_getmsgs(self);
- if (self->sup_timers)
- su_timer_expire(&self->sup_timers, &tout, su_now());
+ if (self->sup_timers || self->sup_deferrable) {
+ su_time_t now = su_now();
+ su_timer_expire(&self->sup_timers, &tout, now);
+ su_timer_expire(&self->sup_deferrable, &tout2, now);
+ }
if (!self->sup_running)
break;
@@ -349,13 +356,13 @@
{
int i;
int timers = 0, messages = 0, events = 0;
- su_duration_t tout = 0, tout0;
+ su_duration_t tout = 0, tout2 = 0;
su_time_t started = su_now(), woken = started, bedtime = woken;
assert(su_port_own_thread(self));
for (self->sup_running = 1; self->sup_running;) {
- tout = 2000;
+ tout = self->sup_max_defer;
timers = 0, messages = 0;
@@ -365,8 +372,12 @@
if (self->sup_head)
messages = self->sup_vtable->su_port_getmsgs(self);
- if (self->sup_timers)
- timers = su_timer_expire(&self->sup_timers, &tout, su_now());
+ if (self->sup_timers || self->sup_deferrable) {
+ su_time_t now = su_now();
+ timers =
+ su_timer_expire(&self->sup_timers, &tout, now) +
+ su_timer_expire(&self->sup_deferrable, &tout2, now);
+ }
if (!self->sup_running)
break;
@@ -404,6 +415,16 @@
self->sup_running = 0;
}
+/** @internal
+ * Check if port is running.
+ *
+ * @param self pointer to port
+ */
+int su_base_port_is_running(su_port_t const *self)
+{
+ return self->sup_running != 0;
+}
+
/** @internal Block until wait object is signaled or timeout.
*
* This function waits for wait objects and the timers associated with
@@ -435,6 +456,9 @@
if (self->sup_timers)
su_timer_expire(&self->sup_timers, &tout, now);
+ if (self->sup_deferrable)
+ su_timer_expire(&self->sup_deferrable, &tout, now);
+
/* if there are messages do a quick wait */
if (self->sup_head)
tout = 0;
@@ -444,15 +468,27 @@
else
tout = SU_WAIT_FOREVER;
- if (self->sup_head)
+ if (self->sup_head) {
if (self->sup_vtable->su_port_getmsgs(self)) {
/* Check for wait events that may have been generated by messages */
if (self->sup_vtable->su_port_wait_events(self, 0))
tout = 0;
}
+ }
- if (self->sup_timers)
- su_timer_expire(&self->sup_timers, &tout, su_now());
+ if (self->sup_timers || self->sup_deferrable) {
+ su_duration_t tout2 = SU_WAIT_FOREVER;
+
+ now = su_now();
+ su_timer_expire(&self->sup_timers, &tout, now);
+ su_timer_expire(&self->sup_deferrable, &tout2, now);
+
+ if (tout == SU_WAIT_FOREVER && tout2 != SU_WAIT_FOREVER) {
+ if (tout2 < self->sup_max_defer)
+ tout2 = self->sup_max_defer;
+ tout = tout2;
+ }
+ }
if (self->sup_head)
tout = 0;
@@ -501,6 +537,22 @@
return &self->sup_timers;
}
+su_timer_queue_t *su_base_port_deferrable(su_port_t *self)
+{
+ return &self->sup_deferrable;
+}
+
+int su_base_port_max_defer(su_port_t *self,
+ su_duration_t *return_duration,
+ su_duration_t *set_duration)
+{
+ if (set_duration && *set_duration > 0)
+ self->sup_max_defer = *set_duration;
+ if (return_duration)
+ *return_duration = self->sup_max_defer;
+ return 0;
+}
+
/* ======================================================================
* Clones
*/
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_devpoll_port.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_devpoll_port.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_devpoll_port.c Wed Feb 11 11:16:44 2009
@@ -127,7 +127,7 @@
su_base_port_incref,
su_devpoll_port_decref,
su_base_port_gsource,
- su_socket_port_send,
+ su_base_port_send,
su_devpoll_port_register,
su_devpoll_port_unregister,
su_devpoll_port_deregister,
@@ -148,6 +148,10 @@
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute,
+ su_base_port_deferrable,
+ su_base_port_max_defer,
+ su_socket_port_wakeup,
+ su_base_port_is_running,
}};
static char const *su_devpoll_port_name(su_port_t const *self)
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_epoll_port.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_epoll_port.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_epoll_port.c Wed Feb 11 11:16:44 2009
@@ -122,7 +122,7 @@
su_base_port_incref,
su_epoll_port_decref,
su_base_port_gsource,
- su_socket_port_send,
+ su_base_port_send,
su_epoll_port_register,
su_epoll_port_unregister,
su_epoll_port_deregister,
@@ -143,6 +143,10 @@
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute,
+ su_base_port_deferrable,
+ su_base_port_max_defer,
+ su_socket_port_wakeup,
+ su_base_port_is_running,
}};
static char const *su_epoll_port_name(su_port_t const *self)
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_kqueue_port.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_kqueue_port.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_kqueue_port.c Wed Feb 11 11:16:44 2009
@@ -119,7 +119,7 @@
su_base_port_incref,
su_kqueue_port_decref,
su_base_port_gsource,
- su_socket_port_send,
+ su_base_port_send,
su_kqueue_port_register,
su_kqueue_port_unregister,
su_kqueue_port_deregister,
@@ -140,6 +140,10 @@
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute,
+ su_base_port_deferrable,
+ su_base_port_max_defer,
+ su_socket_port_wakeup,
+ su_base_port_is_running,
}};
static char const *su_kqueue_port_name(su_port_t const *self)
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_osx_runloop.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_osx_runloop.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_osx_runloop.c Wed Feb 11 11:16:44 2009
@@ -204,6 +204,10 @@
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute,
+ su_base_port_deferrable,
+ su_base_port_max_defer,
+ su_socket_port_wakeup,
+ su_base_port_is_running,
}};
/* XXX - mela static void su_osx_port_destroy(su_port_t *self); */
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_poll_port.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_poll_port.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_poll_port.c Wed Feb 11 11:16:44 2009
@@ -120,7 +120,7 @@
su_base_port_incref,
su_poll_port_decref,
su_base_port_gsource,
- su_socket_port_send,
+ su_base_port_send,
su_poll_port_register,
su_poll_port_unregister,
su_poll_port_deregister,
@@ -141,6 +141,10 @@
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute,
+ su_base_port_deferrable,
+ su_base_port_max_defer,
+ su_socket_port_wakeup,
+ su_base_port_is_running,
}};
static char const *su_poll_port_name(su_port_t const *self)
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_port.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_port.h (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_port.h Wed Feb 11 11:16:44 2009
@@ -150,6 +150,14 @@
int (*su_port_execute)(su_task_r const task,
int (*function)(void *), void *arg,
int *return_value);
+
+ /* >= 1.12.11 */
+ su_timer_queue_t *(*su_port_deferrable)(su_port_t *port);
+ int (*su_port_max_defer)(su_port_t *port,
+ su_duration_t *return_duration,
+ su_duration_t *set_duration);
+ int (*su_port_wakeup)(su_port_t *port);
+ int (*su_port_is_running)(su_port_t const *port);
} su_port_vtable_t;
SOFIAPUBFUN su_port_t *su_port_create(void)
@@ -244,6 +252,12 @@
return base->sup_vtable->su_port_send(self, rmsg);
}
+su_inline
+int su_port_wakeup(su_port_t *self)
+{
+ su_virtual_port_t *base = (su_virtual_port_t *)self;
+ return base->sup_vtable->su_port_wakeup(self);
+}
su_inline
int su_port_register(su_port_t *self,
@@ -372,7 +386,7 @@
}
su_inline
-su_timer_t **su_port_timers(su_port_t *self)
+su_timer_queue_t *su_port_timers(su_port_t *self)
{
su_virtual_port_t *base = (su_virtual_port_t *)self;
return base->sup_vtable->su_port_timers(self);
@@ -399,6 +413,41 @@
return base->sup_vtable->su_port_getmsgs_from(self, cloneport);
}
+/** Extension from >= 1.12.11 */
+
+su_inline
+su_timer_queue_t *su_port_deferrable(su_port_t *self)
+{
+ su_virtual_port_t *base = (su_virtual_port_t *)self;
+
+ if (base == NULL)
+ return (void *)(errno = EFAULT), NULL;
+
+ return base->sup_vtable->su_port_deferrable(self);
+}
+
+su_inline
+int su_port_max_defer(su_port_t *self,
+ su_duration_t *return_duration,
+ su_duration_t *set_duration)
+{
+ su_virtual_port_t *base = (su_virtual_port_t *)self;
+
+ if (base == NULL)
+ return (errno = EFAULT), -1;
+
+ return base->sup_vtable->su_port_max_defer(self,
+ return_duration,
+ set_duration);
+}
+
+su_inline
+int su_port_is_running(su_port_t const *self)
+{
+ su_virtual_port_t *base = (su_virtual_port_t *)self;
+ return base && base->sup_vtable->su_port_is_running(self);
+}
+
SOFIAPUBFUN void su_port_wait(su_clone_r rclone);
SOFIAPUBFUN int su_port_execute(su_task_r const task,
@@ -427,7 +476,9 @@
su_msg_t *sup_head, **sup_tail;
/* Timer list */
- su_timer_queue_t sup_timers;
+ su_timer_queue_t sup_timers, sup_deferrable;
+
+ su_duration_t sup_max_defer; /**< Maximum time to defer */
unsigned sup_running; /**< In su_root_run() loop? */
} su_base_port_t;
@@ -468,7 +519,7 @@
SOFIAPUBFUN int su_base_port_remove_prepoll(su_port_t *self, su_root_t *root);
-SOFIAPUBFUN su_timer_t **su_base_port_timers(su_port_t *self);
+SOFIAPUBFUN su_timer_queue_t *su_base_port_timers(su_port_t *self);
SOFIAPUBFUN int su_base_port_multishot(su_port_t *self, int multishot);
@@ -479,6 +530,14 @@
su_root_deinit_f deinit);
SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone);
+SOFIAPUBFUN su_timer_queue_t *su_base_port_deferrable(su_port_t *self);
+
+SOFIAPUBFUN int su_base_port_max_defer(su_port_t *self,
+ su_duration_t *return_duration,
+ su_duration_t *set_duration);
+
+SOFIAPUBFUN int su_base_port_is_running(su_port_t const *self);
+
/* ---------------------------------------------------------------------- */
#if SU_HAVE_PTHREADS
@@ -493,7 +552,7 @@
pthread_t sup_tid;
pthread_mutex_t sup_obtained[1];
-#if 0
+#if 0 /* Pausing and resuming are not used */
pthread_mutex_t sup_runlock[1];
pthread_cond_t sup_resume[1];
short sup_paused; /**< True if thread is paused */
@@ -535,7 +594,6 @@
int (*function)(void *), void *arg,
int *return_value);
-
#if 0
SOFIAPUBFUN int su_pthread_port_pause(su_port_t *self);
SOFIAPUBFUN int su_pthread_port_resume(su_port_t *self);
@@ -570,6 +628,7 @@
su_port_vtable_t const *);
SOFIAPUBFUN void su_socket_port_deinit(su_socket_port_t *self);
SOFIAPUBFUN int su_socket_port_send(su_port_t *self, su_msg_r rmsg);
+SOFIAPUBFUN int su_socket_port_wakeup(su_port_t *self);
SOFIA_END_DECLS
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c Wed Feb 11 11:16:44 2009
@@ -315,6 +315,9 @@
task->sut_root->sur_magic = arg->magic;
task->sut_root->sur_deinit = arg->deinit;
+ su_root_set_max_defer(task->sut_root,
+ su_root_get_max_defer(arg->parent));
+
if (arg->init(task->sut_root, arg->magic) == 0) {
su_pthread_port_return_to_parent(arg, 0), arg = NULL;
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_root.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_root.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_root.c Wed Feb 11 11:16:44 2009
@@ -86,6 +86,8 @@
* - su_root_run() [Do not call from cloned task]
* - su_root_break() [Do not call from cloned task]
* - su_root_step() [Do not call from cloned task]
+ * - su_root_get_max_defer()
+ * - su_root_set_max_defer()
* - su_root_task()
*
* New tasks can be created via su_clone_start() function.
@@ -127,6 +129,7 @@
* Tasks
*/
+/** NULL task. */
su_task_r const su_task_null = SU_TASK_R_INIT;
#define SU_TASK_ZAP(t, f) \
@@ -259,13 +262,13 @@
*
* @retval true (nonzero) if task is not stopped,
* @retval zero if it is null or stopped.
+ *
+ * @note A task sharing thread with another task is considered stopped when
+ * ever the the main task is stopped.
*/
int su_task_is_running(su_task_r const task)
{
- return
- task &&
- task->sut_port &&
- task->sut_root;
+ return task && task->sut_root && su_port_is_running(task->sut_port);
}
/** @internal
@@ -318,14 +321,43 @@
*
* @param task task handle
*
- * @return A timer list of the task. If there are no timers, it returns
- * NULL.
+ * @return A timer list of the task.
*/
su_timer_queue_t *su_task_timers(su_task_r const task)
{
return task->sut_port ? su_port_timers(task->sut_port) : NULL;
}
+/**Return the queue for deferrable timers associated with given task.
+ *
+ * @param task task handle
+ *
+ * @return A timer list of the task.
+ *
+ * @NEW_1_12_11
+ */
+su_timer_queue_t *su_task_deferrable(su_task_r const task)
+{
+ return task ? su_port_deferrable(task->sut_port) : NULL;
+}
+
+/** Wakeup a task.
+ *
+ * Wake up a task. This function is mainly useful when using deferrable
+ * timers executed upon wakeup.
+ *
+ * @param task task handle
+ *
+ * @retval 0 if succesful
+ * @retval -1 upon an error
+ *
+ * @NEW_1_12_11
+ */
+int su_task_wakeup(su_task_r const task)
+{
+ return task ? su_port_wakeup(task->sut_port) : -1;
+}
+
/** Execute the @a function by @a task thread.
*
* @retval 0 if successful
@@ -447,6 +479,10 @@
unregistered = su_port_unregister_all(port, self);
reset = su_timer_reset_all(su_task_timers(self->sur_task), self->sur_task);
+ if (su_task_deferrable(self->sur_task))
+ reset += su_timer_reset_all(su_task_deferrable(self->sur_task),
+ self->sur_task);
+
if (unregistered || reset)
SU_DEBUG_1(("su_root_destroy: "
"%u registered waits, %u timers\n",
@@ -601,6 +637,56 @@
return su_port_unregister(self->sur_port, self, wait, callback, arg);
}
+/** Set maximum defer time.
+ *
+ * The deferrable timers can be deferred until the task is otherwise
+ * activated, however, they are deferred no longer than the maximum defer
+ * time. The maximum defer time determines also the maximum time during
+ * which task waits for events while running. The maximum defer time is 15
+ * seconds by default.
+ *
+ * Cloned tasks inherit the maximum defer time.
+ *
+ * @param self pointer to root object
+ * @param max_defer maximum defer time in milliseconds
+ *
+ * @retval 0 when successful
+ * @retval -1 upon an error
+ *
+ * @sa su_timer_deferrable()
+ *
+ * @NEW_1_12_11
+ */
+int su_root_set_max_defer(su_root_t *self, su_duration_t max_defer)
+{
+ if (!self)
+ return -1;
+
+ return su_port_max_defer(self->sur_port, &max_defer, &max_defer);
+}
+
+/** Get maximum defer time.
+ *
+ * The deferrable timers can be deferred until the task is otherwise
+ * activated, however, they are deferred no longer than the maximum defer
+ * time. The maximum defer time is 15 seconds by default.
+ *
+ * @param root pointer to root object
+ *
+ * @return Maximum defer time
+ *
+ * @NEW_1_12_7
+ */
+su_duration_t su_root_get_max_defer(su_root_t const *self)
+{
+ su_duration_t max_defer = SU_WAIT_MAX;
+
+ if (self != NULL)
+ su_port_max_defer(self->sur_port, &max_defer, NULL);
+
+ return max_defer;
+}
+
/** Remove a su_wait_t registration.
*
* The function su_root_deregister() deregisters a su_wait_t object. The
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_select_port.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_select_port.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_select_port.c Wed Feb 11 11:16:44 2009
@@ -139,7 +139,7 @@
su_base_port_incref,
su_select_port_decref,
su_base_port_gsource,
- su_socket_port_send,
+ su_base_port_send,
su_select_port_register,
su_select_port_unregister,
su_select_port_deregister,
@@ -160,6 +160,10 @@
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute,
+ su_base_port_deferrable,
+ su_base_port_max_defer,
+ su_socket_port_wakeup,
+ su_base_port_is_running,
}};
static char const *su_select_port_name(su_port_t const *self)
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_socket_port.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_socket_port.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_socket_port.c Wed Feb 11 11:16:44 2009
@@ -179,23 +179,17 @@
su_pthread_port_deinit(self);
}
-/** @internal Send a message to the port. */
-int su_socket_port_send(su_port_t *self, su_msg_r rmsg)
+/** @internal Wake up the port. */
+int su_socket_port_wakeup(su_port_t *self)
{
- int wakeup = su_base_port_send(self, rmsg);
+ assert(self->sup_mbox[SU_MBOX_SEND] != INVALID_SOCKET);
- if (wakeup < 0)
- return -1;
-
- if (wakeup) {
- assert(self->sup_mbox[SU_MBOX_SEND] != INVALID_SOCKET);
-
- if (send(self->sup_mbox[SU_MBOX_SEND], "X", 1, 0) == -1) {
+ if (!su_pthread_port_own_thread(self) &&
+ send(self->sup_mbox[SU_MBOX_SEND], "X", 1, 0) == -1) {
#if HAVE_SOCKETPAIR
- if (su_errno() != EWOULDBLOCK)
+ if (su_errno() != EWOULDBLOCK)
#endif
- su_perror("su_msg_send: send()");
- }
+ su_perror("su_msg_send: send()");
}
return 0;
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c Wed Feb 11 11:16:44 2009
@@ -164,7 +164,9 @@
su_timer_arg_t *sut_arg; /**< Pointer to argument data */
su_time_t sut_run; /**< When this timer was last waken up */
unsigned sut_woken; /**< Timer has waken up this many times */
- unsigned short sut_running; /**< Timer is running */
+
+ unsigned sut_running:2;/**< Timer is running */
+ unsigned sut_deferrable:1;/**< Timer can be deferrable */
};
/** Timer running status */
@@ -246,9 +248,9 @@
* @retval NULL upon an error
*/
static
-su_timer_queue_t *su_timer_tree(su_timer_t const *t,
- int use_sut_duration,
- char const *caller)
+su_timer_queue_t *su_timer_queue(su_timer_t const *t,
+ int use_sut_duration,
+ char const *caller)
{
su_timer_queue_t *timers;
@@ -265,7 +267,10 @@
return NULL;
}
- timers = su_task_timers(t->sut_task);
+ if (t->sut_deferrable)
+ timers = su_task_deferrable(t->sut_task);
+ else
+ timers = su_task_timers(t->sut_task);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t, "invalid timer"));
@@ -285,7 +290,7 @@
* Allocate and initialize an instance of su_timer_t.
*
* @param task a task for root object with which the timer will be associated
- * @param msec the default duration of the timer
+ * @param msec the default duration of the timer in milliseconds
*
* @return A pointer to allocated timer instance, NULL on error.
*/
@@ -307,6 +312,7 @@
return retval;
}
+
/** Destroy a timer.
*
* Deinitialize and free an instance of su_timer_t.
@@ -322,6 +328,7 @@
}
}
+
/** Set the timer for the given @a interval.
*
* Sets (starts) the given timer to expire after the specified duration.
@@ -338,7 +345,7 @@
su_timer_arg_t *arg,
su_duration_t interval)
{
- su_timer_queue_t *timers = su_timer_tree(t, 0, "su_timer_set_interval");
+ su_timer_queue_t *timers = su_timer_queue(t, 0, "su_timer_set_interval");
return su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
}
@@ -359,7 +366,7 @@
su_timer_f wakeup,
su_timer_arg_t *arg)
{
- su_timer_queue_t *timers = su_timer_tree(t, 1, "su_timer_set");
+ su_timer_queue_t *timers = su_timer_queue(t, 1, "su_timer_set");
return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
}
@@ -380,7 +387,7 @@
su_wakeup_arg_t *arg,
su_time_t when)
{
- su_timer_queue_t *timers = su_timer_tree(t, 0, "su_timer_set_at");
+ su_timer_queue_t *timers = su_timer_queue(t, 0, "su_timer_set_at");
return su_timer_set0(timers, t, wakeup, arg, when, 0);
}
@@ -407,7 +414,7 @@
su_timer_f wakeup,
su_timer_arg_t *arg)
{
- su_timer_queue_t *timers = su_timer_tree(t, 1, "su_timer_run");
+ su_timer_queue_t *timers = su_timer_queue(t, 1, "su_timer_run");
su_time_t now;
if (timers == NULL)
@@ -440,7 +447,7 @@
su_timer_f wakeup,
su_timer_arg_t *arg)
{
- su_timer_queue_t *timers = su_timer_tree(t, 1, "su_timer_set_for_ever");
+ su_timer_queue_t *timers = su_timer_queue(t, 1, "su_timer_set_for_ever");
su_time_t now;
if (timers == NULL)
@@ -463,7 +470,7 @@
*/
int su_timer_reset(su_timer_t *t)
{
- su_timer_queue_t *timers = su_timer_tree(t, 0, "su_timer_reset");
+ su_timer_queue_t *timers = su_timer_queue(t, 0, "su_timer_reset");
if (timers == NULL)
return -1;
@@ -508,7 +515,7 @@
if (SU_TIME_CMP(t->sut_when, now) > 0) {
su_duration_t at = su_duration(t->sut_when, now);
- if (at < *timeout)
+ if (at < *timeout || *timeout < 0)
*timeout = at;
break;
@@ -622,3 +629,31 @@
return t ? su_task_root(t->sut_task) : NULL;
}
+
+/** Change timer as deferrable (or as undeferrable).
+ *
+ * A deferrable timer is executed after the given timeout, however, the task
+ * tries to avoid being woken up only because the timeout. Deferable timers
+ * have their own queue and timers there are ignored when calculating the
+ * timeout for epoll()/select()/whatever unless the timeout would exceed the
+ * maximum defer time. The maximum defer time is 15 seconds by default, but
+ * it can be modified by su_root_set_max_defer().
+ *
+ * @param t pointer to the timer
+ * @param value make timer deferrable if true, undeferrable if false
+ *
+ * @return 0 if succesful, -1 upon an error
+ *
+ * @sa su_root_set_max_defer()
+ *
+ * @NEW_1_12_7
+ */
+int su_timer_deferrable(su_timer_t *t, int value)
+{
+ if (t == NULL || su_task_deferrable(t->sut_task) == NULL)
+ return errno = EINVAL, -1;
+
+ t->sut_deferrable = value != 0;
+
+ return 0;
+}
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_win32_port.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_win32_port.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_win32_port.c Wed Feb 11 11:16:44 2009
@@ -118,7 +118,7 @@
su_base_port_incref,
su_wsevent_port_decref,
su_base_port_gsource,
- su_socket_port_send,
+ su_base_port_send,
su_wsevent_port_register,
su_wsevent_port_unregister,
su_wsevent_port_deregister,
@@ -139,6 +139,10 @@
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute,
+ su_base_port_deferrable,
+ su_base_port_max_defer,
+ su_socket_port_wakeup,
+ su_base_port_is_running,
}};
static char const *su_wsevent_port_name(su_port_t const *self)
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c Wed Feb 11 11:16:44 2009
@@ -61,6 +61,8 @@
#include <pthread.h>
#endif
+#define ALARM_IN_SECONDS 120
+
struct test_ep_s {
test_ep_t *next, **prev, **list;
int i;
@@ -99,6 +101,8 @@
unsigned rt_executed:1;
+ unsigned rt_t1:1, rt_t2:1;
+
unsigned :0;
test_ep_at rt_ep[5];
@@ -161,7 +165,6 @@
END();
}
-
#if SU_HAVE_PTHREADS
#include <pthread.h>
@@ -589,6 +592,61 @@
rt->rt_sent_reporter = 1;
}
+static void expire1(root_test_t *rt, su_timer_t *t, su_timer_arg_t *arg)
+{
+ (void)arg;
+ rt->rt_t1 = 1;
+}
+
+static void expire2(root_test_t *rt, su_timer_t *t, su_timer_arg_t *arg)
+{
+ (void)arg;
+ rt->rt_t2 = 1;
+}
+
+int timer_test(root_test_t rt[1])
+{
+ BEGIN();
+
+ su_timer_t *t1, *t2;
+ su_duration_t defer;
+
+ TEST_1(t1 = su_timer_create(su_root_task(rt->rt_root), 100));
+ TEST_1(t2 = su_timer_create(su_root_task(rt->rt_root), 110));
+
+ rt->rt_t1 = rt->rt_t2 = 0;
+
+ TEST_1(su_root_step(rt->rt_root, 0) == SU_WAIT_FOREVER);
+
+ TEST_1(su_root_set_max_defer(rt->rt_root, 30000) != -1);
+ TEST(su_root_get_max_defer(rt->rt_root), 30000);
+
+ if (su_timer_deferrable(t1, 1) == 0) {
+ /*
+ * If only a deferrable timer is set, su_root_step() should return
+ * about the maximum defer time, which now defaults to 15 seconds
+ */
+ TEST(su_timer_set(t1, expire1, NULL), 0);
+ defer = su_root_step(rt->rt_root, 0);
+ TEST_1(defer > 100);
+ }
+ else {
+ TEST(su_timer_set(t1, expire1, NULL), 0);
+ }
+
+ TEST(su_timer_set(t2, expire2, NULL), 0);
+
+ while (su_root_step(rt->rt_root, 100) != SU_WAIT_FOREVER)
+ ;
+
+ TEST_1(rt->rt_t1 && rt->rt_t2);
+
+ su_timer_destroy(t1);
+ su_timer_destroy(t2);
+
+ END();
+}
+
static int set_execute_bit_and_return_3(void *void_rt)
{
root_test_t *rt = void_rt;
@@ -612,13 +670,34 @@
su_task_cmp(su_msg_to(msg), su_task_null) == 0;
}
-static int clone_test(root_test_t rt[1])
+static void expire1destroy(root_test_t *rt, su_timer_t *t, su_timer_arg_t *arg)
+{
+ (void)arg;
+ rt->rt_t1 = 1;
+ su_timer_destroy(t);
+}
+
+static int set_deferrable_timer(void *void_rt)
+{
+ root_test_t *rt = void_rt;
+ su_timer_t *t1;
+
+ TEST_1(t1 = su_timer_create(su_clone_task(rt->rt_clone), 100));
+ TEST_1(su_timer_deferrable(t1, 1) == 0);
+ TEST(su_timer_set(t1, expire1destroy, NULL), 0);
+
+ return 0;
+}
+
+static int clone_test(root_test_t rt[1], int multithread)
{
BEGIN();
su_msg_r m = SU_MSG_R_INIT;
int retval;
+ su_root_threading(rt->rt_root, multithread);
+
rt->rt_fail_init = 0;
rt->rt_fail_deinit = 0;
rt->rt_success_init = 0;
@@ -635,6 +714,10 @@
TEST_1(rt->rt_fail_init);
TEST_1(rt->rt_fail_deinit);
+ /* Defer longer than maximum allowed run time */
+ TEST_1(su_root_set_max_defer(rt->rt_root, ALARM_IN_SECONDS * 1000) != -1);
+ TEST(su_root_get_max_defer(rt->rt_root), ALARM_IN_SECONDS * 1000);
+
TEST(su_clone_start(rt->rt_root,
rt->rt_clone,
rt,
@@ -643,6 +726,7 @@
TEST_1(rt->rt_success_init);
TEST_1(!rt->rt_success_deinit);
+ /* Test su_task_execute() */
retval = -1;
rt->rt_executed = 0;
TEST(su_task_execute(su_clone_task(rt->rt_clone),
@@ -666,6 +750,28 @@
TEST(rt->rt_msg_received, 1);
+ if (multithread) {
+ TEST_1(su_task_is_running(su_clone_task(rt->rt_clone)));
+ }
+ else {
+ TEST_1(!su_task_is_running(su_clone_task(rt->rt_clone)));
+ }
+
+ /* Test su_wakeup() */
+ if (multithread) {
+ retval = -1;
+ rt->rt_t1 = 0;
+ TEST(su_task_execute(su_clone_task(rt->rt_clone),
+ set_deferrable_timer, rt,
+ &retval), 0);
+ TEST(retval, 0);
+
+ while (rt->rt_t1 == 0) {
+ TEST(su_root_step(rt->rt_root, 100), SU_WAIT_FOREVER);
+ su_task_wakeup(su_clone_task(rt->rt_clone));
+ }
+ }
+
/* Make sure 3-way handshake is done as expected */
TEST(su_msg_create(m,
su_clone_task(rt->rt_clone),
@@ -707,10 +813,21 @@
exit(exitcode);
}
+#if HAVE_ALARM
+#include <signal.h>
+
+static RETSIGTYPE sig_alarm(int s)
+{
+ fprintf(stderr, "%s: FAIL! test timeout!\n", name);
+ exit(1);
+}
+#endif
+
int main(int argc, char *argv[])
{
root_test_t *rt, rt0[1] = {{{ SU_HOME_INIT(rt0) }}}, rt1[1];
int retval = 0;
+ int no_alarm = 0;
int i;
struct {
@@ -746,6 +863,8 @@
rt->rt_flags |= tst_verbatim;
else if (strcmp(argv[i], "-a") == 0)
rt->rt_flags |= tst_abort;
+ else if (strcmp(argv[i], "--no-alarm") == 0)
+ no_alarm = 1;
#if SU_HAVE_IN6
else if (strcmp(argv[i], "-6") == 0)
rt->rt_family = AF_INET6;
@@ -754,6 +873,13 @@
usage(1);
}
+#if HAVE_ALARM
+ if (!no_alarm) {
+ signal(SIGALRM, sig_alarm);
+ alarm(ALARM_IN_SECONDS);
+ }
+#endif
+
#if HAVE_OPEN_C
rt->rt_flags |= tst_verbatim;
#endif
@@ -770,10 +896,9 @@
retval |= init_test(rt, prefer[i].name, prefer[i].create, prefer[i].start);
retval |= register_test(rt);
retval |= event_test(rt);
- su_root_threading(rt->rt_root, 1);
- retval |= clone_test(rt);
- su_root_threading(rt->rt_root, 0);
- retval |= clone_test(rt);
+ retval |= timer_test(rt);
+ retval |= clone_test(rt, 1);
+ retval |= clone_test(rt, 0);
retval |= deinit_test(rt);
} while (prefer[++i].create);
1
0
[commit] r11851 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/su
by FreeSWITCH SVN 11 Feb '09
by FreeSWITCH SVN 11 Feb '09
11 Feb '09
Author: mikej
Date: Wed Feb 11 11:16:05 2009
New Revision: 11851
Log:
Wed Jan 28 12:02:55 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* su_timer.c: removed redundant checks
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Wed Feb 11 11:16:05 2009
@@ -1 +1 @@
-Wed Feb 11 11:15:31 CST 2009
+Wed Feb 11 11:15:57 CST 2009
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c Wed Feb 11 11:16:05 2009
@@ -156,7 +156,6 @@
*/
struct su_timer_s {
- /** Pointers within red-black tree */
su_task_r sut_task; /**< Task reference */
size_t sut_heap_index; /**< Timer is set (inserted in heap) */
su_time_t sut_when; /**< When timer should be waken up next time */
@@ -219,8 +218,6 @@
{
int retval;
- assert(timers);
-
if (timers == NULL)
return -1;
@@ -343,9 +340,6 @@
{
su_timer_queue_t *timers = su_timer_tree(t, 0, "su_timer_set_interval");
- if (t == NULL)
- return -1;
-
return su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
}
@@ -367,9 +361,6 @@
{
su_timer_queue_t *timers = su_timer_tree(t, 1, "su_timer_set");
- if (timers == NULL)
- return -1;
-
return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
}
@@ -391,9 +382,6 @@
{
su_timer_queue_t *timers = su_timer_tree(t, 0, "su_timer_set_at");
- if (timers == NULL)
- return -1;
-
return su_timer_set0(timers, t, wakeup, arg, when, 0);
}
1
0
[commit] r11850 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/su
by FreeSWITCH SVN 11 Feb '09
by FreeSWITCH SVN 11 Feb '09
11 Feb '09
Author: mikej
Date: Wed Feb 11 11:15:37 2009
New Revision: 11850
Log:
Wed Jan 28 12:01:13 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* su_timer.c: timers_remove() now set sut_heap_index to 0
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Wed Feb 11 11:15:37 2009
@@ -1 +1 @@
-Wed Feb 11 11:14:50 CST 2009
+Wed Feb 11 11:15:31 CST 2009
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c Wed Feb 11 11:15:37 2009
@@ -225,7 +225,7 @@
return -1;
if (SU_TIMER_IS_SET(t))
- timers_remove(timers[0], t->sut_heap_index)->sut_heap_index = 0;
+ timers_remove(timers[0], t->sut_heap_index);
t->sut_wakeup = wakeup;
t->sut_arg = arg;
@@ -481,7 +481,7 @@
return -1;
if (SU_TIMER_IS_SET(t))
- timers_remove(timers[0], t->sut_heap_index)->sut_heap_index = 0;
+ timers_remove(timers[0], t->sut_heap_index);
t->sut_wakeup = NULL;
t->sut_arg = NULL;
@@ -526,7 +526,7 @@
break;
}
- timers_remove(timers[0], 1)->sut_heap_index = 0;
+ timers_remove(timers[0], 1);
f = t->sut_wakeup; t->sut_wakeup = NULL;
assert(f);
@@ -609,7 +609,7 @@
if (su_task_cmp(task, t->sut_task))
continue;
- timers_remove(timers[0], i)->sut_heap_index = 0;
+ timers_remove(timers[0], i);
su_free(NULL, t);
n++;
1
0
[commit] r11849 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/su
by FreeSWITCH SVN 11 Feb '09
by FreeSWITCH SVN 11 Feb '09
11 Feb '09
Author: mikej
Date: Wed Feb 11 11:14:57 2009
New Revision: 11849
Log:
Wed Jan 28 12:00:26 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* su_timer.c: no more type-punning
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Wed Feb 11 11:14:57 2009
@@ -1 +1 @@
-Wed Feb 11 11:14:27 CST 2009
+Wed Feb 11 11:14:50 CST 2009
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c Wed Feb 11 11:14:57 2009
@@ -33,12 +33,15 @@
#include "config.h"
#include <sys/types.h>
-#include <sofia-sip/heap.h>
+#include "sofia-sip/heap.h"
typedef union {
void *private;
/* Use for debugging */
- struct timers_priv { size_t _size, _used; struct su_timer_s * _heap[2]; } *actual;
+ struct timers_priv {
+ size_t _size, _used;
+ struct su_timer_s * _heap[2];
+ } *actual;
} su_timer_heap_t;
#define SU_TIMER_QUEUE_T su_timer_heap_t
1
0
[commit] r11848 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/su
by FreeSWITCH SVN 11 Feb '09
by FreeSWITCH SVN 11 Feb '09
11 Feb '09
Author: mikej
Date: Wed Feb 11 11:14:33 2009
New Revision: 11848
Log:
Wed Jan 28 11:52:34 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* su_timer.c: using heap (instead of red-black tree) for keeping timers sorted
Re-recorded 20070704230449-65a35-f0434c75b0f58a069806e81942c0d5e0821dc9d3
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Wed Feb 11 11:14:33 2009
@@ -1 +1 @@
-Wed Feb 11 11:13:59 CST 2009
+Wed Feb 11 11:14:27 CST 2009
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c Wed Feb 11 11:14:33 2009
@@ -32,7 +32,17 @@
#include "config.h"
-#include "su_port.h"
+#include <sys/types.h>
+#include <sofia-sip/heap.h>
+
+typedef union {
+ void *private;
+ /* Use for debugging */
+ struct timers_priv { size_t _size, _used; struct su_timer_s * _heap[2]; } *actual;
+} su_timer_heap_t;
+
+#define SU_TIMER_QUEUE_T su_timer_heap_t
+
#include "sofia-sip/su.h"
#include "sofia-sip/su_wait.h"
#include "sofia-sip/su_alloc.h"
@@ -144,8 +154,8 @@
struct su_timer_s {
/** Pointers within red-black tree */
- su_timer_t *sut_left, *sut_right, *sut_parent;
su_task_r sut_task; /**< Task reference */
+ size_t sut_heap_index; /**< Timer is set (inserted in heap) */
su_time_t sut_when; /**< When timer should be waken up next time */
su_duration_t sut_duration; /**< Timer duration */
su_timer_f sut_wakeup; /**< Function to call when waken up */
@@ -153,9 +163,6 @@
su_time_t sut_run; /**< When this timer was last waken up */
unsigned sut_woken; /**< Timer has waken up this many times */
unsigned short sut_running; /**< Timer is running */
-
- unsigned char sut_black; /**< Black node */
- unsigned char sut_set; /**< Timer is set (inserted in tree) */
};
/** Timer running status */
@@ -165,35 +172,35 @@
run_for_ever = 2 /**< Do not compensate */
};
-#define SU_TIMER_IS_SET(sut) ((sut)->sut_set)
+#define SU_TIMER_IS_SET(sut) ((sut)->sut_heap_index != 0)
+
+HEAP_DECLARE(su_inline, su_timer_queue_t, timers_, su_timer_t *);
+
+su_inline void timers_set(su_timer_t **array, size_t index, su_timer_t *t)
+{
+ array[t->sut_heap_index = index] = t;
+}
+
+su_inline int timers_less(su_timer_t *a, su_timer_t *b)
+{
+ return
+ a->sut_when.tv_sec < b->sut_when.tv_sec ||
+ (a->sut_when.tv_sec == b->sut_when.tv_sec &&
+ a->sut_when.tv_usec < b->sut_when.tv_usec);
+}
+
+su_inline void *timers_alloc(void *argument, void *memory, size_t size)
+{
+ (void)argument;
+
+ if (size)
+ return realloc(memory, size);
+ else
+ return free(memory), NULL;
+}
-/* Accessor macros for rbtree */
-#define LEFT(sut) ((sut)->sut_left)
-#define RIGHT(sut) ((sut)->sut_right)
-#define PARENT(sut) ((sut)->sut_parent)
-#define SET_RED(sut) ((sut)->sut_black = 0)
-#define SET_BLACK(sut) ((sut)->sut_black = 1)
-#define CMP(a, b) SU_TIME_CMP((a)->sut_when, (b)->sut_when)
-#define IS_RED(sut) ((sut) && (sut)->sut_black == 0)
-#define IS_BLACK(sut) (!(sut) || (sut)->sut_black == 1)
-#define COPY_COLOR(dst, src) ((dst)->sut_black = (src)->sut_black)
-#define INSERT(sut) ((sut)->sut_set = 1)
-#define REMOVE(sut) ((sut)->sut_set = 0, \
- (sut)->sut_left = (sut)->sut_right = (sut)->sut_parent = NULL)
-
-RBTREE_PROTOS(su_inline, timers, su_timer_t);
-
-su_inline int timers_append(su_timer_queue_t *, su_timer_t *);
-su_inline void timers_remove(su_timer_queue_t *, su_timer_t *);
-su_inline su_timer_t *timers_succ(su_timer_t const *);
-su_inline su_timer_t *timers_prec(su_timer_t const *);
-su_inline su_timer_t *timers_first(su_timer_t const *);
-su_inline su_timer_t *timers_last(su_timer_t const *);
-
-RBTREE_BODIES(su_inline, timers, su_timer_t,
- LEFT, RIGHT, PARENT,
- IS_RED, SET_RED, IS_BLACK, SET_BLACK, COPY_COLOR,
- CMP, INSERT, REMOVE);
+HEAP_BODIES(su_inline, su_timer_queue_t, timers_, su_timer_t *,
+ timers_less, timers_set, timers_alloc, NULL);
/**@internal Set the timer.
*
@@ -207,34 +214,30 @@
su_time_t when,
su_duration_t offset)
{
+ int retval;
+
+ assert(timers);
+
+ if (timers == NULL)
+ return -1;
+
if (SU_TIMER_IS_SET(t))
- timers_remove(timers, t);
+ timers_remove(timers[0], t->sut_heap_index)->sut_heap_index = 0;
t->sut_wakeup = wakeup;
t->sut_arg = arg;
t->sut_when = su_time_add(when, offset);
- return timers_append(timers, t);
-}
-
-/**@internal Reset the timer.
- *
- * @retval 0 when successful (always)
- */
-su_inline int
-su_timer_reset0(su_timer_queue_t *timers,
- su_timer_t *t)
-{
- if (SU_TIMER_IS_SET(t))
- timers_remove(timers, t);
-
- t->sut_wakeup = NULL;
- t->sut_arg = NULL;
- t->sut_running = reset;
+ if (timers_is_full(timers[0])) {
+ timers_resize(NULL, timers, 0);
+ assert(!timers_is_full(timers[0]));
+ if (timers_is_full(timers[0]))
+ return -1;
+ }
- memset(&t->sut_run, 0, sizeof(t->sut_run));
+ retval = timers_add(timers[0], t); assert(retval == 0);
- return 0;
+ return retval;
}
/**@internal Validate timer @a t and return pointer to per-port timer tree.
@@ -255,12 +258,6 @@
return NULL;
}
- timers = su_task_timers(t->sut_task);
-
- if (timers == NULL)
- SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
- "invalid timer"));
-
if (use_sut_duration && t->sut_duration == 0) {
assert(t->sut_duration > 0);
SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
@@ -268,6 +265,17 @@
return NULL;
}
+ timers = su_task_timers(t->sut_task);
+
+ if (timers == NULL) {
+ SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t, "invalid timer"));
+ return NULL;
+ }
+ else if (timers_is_full(timers[0]) && timers_resize(NULL, timers, 0) == -1) {
+ SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t, "timer queue failed"));
+ return NULL;
+ }
+
return timers;
}
@@ -308,9 +316,7 @@
void su_timer_destroy(su_timer_t *t)
{
if (t) {
- su_timer_queue_t *timers = su_task_timers(t->sut_task);
- if (timers)
- su_timer_reset0(timers, t);
+ su_timer_reset(t);
su_task_deinit(t->sut_task);
su_free(NULL, t);
}
@@ -471,7 +477,16 @@
if (timers == NULL)
return -1;
- return su_timer_reset0(timers, t);
+ if (SU_TIMER_IS_SET(t))
+ timers_remove(timers[0], t->sut_heap_index)->sut_heap_index = 0;
+
+ t->sut_wakeup = NULL;
+ t->sut_arg = NULL;
+ t->sut_running = reset;
+
+ memset(&t->sut_run, 0, sizeof(t->sut_run));
+
+ return 0;
}
/** @internal Check for expired timers in queue.
@@ -495,16 +510,20 @@
su_timer_f f;
int n = 0;
- if (!*timers)
- return n;
+ if (timers_used(timers[0]) == 0)
+ return 0;
+
+ while ((t = timers_get(timers[0], 1))) {
+ if (SU_TIME_CMP(t->sut_when, now) > 0) {
+ su_duration_t at = su_duration(t->sut_when, now);
- for (;;) {
- t = timers_first(*timers);
+ if (at < *timeout)
+ *timeout = at;
- if (t == NULL || SU_TIME_CMP(t->sut_when, now) > 0)
break;
+ }
- timers_remove(timers, t);
+ timers_remove(timers[0], 1)->sut_heap_index = 0;
f = t->sut_wakeup; t->sut_wakeup = NULL;
assert(f);
@@ -534,13 +553,6 @@
}
}
- if (t) {
- su_duration_t at = su_duration(t->sut_when, now);
-
- if (at < *timeout)
- *timeout = at;
- }
-
return n;
}
@@ -548,9 +560,16 @@
/** Calculate duration in milliseconds until next timer expires. */
su_duration_t su_timer_next_expires(su_timer_t const * t, su_time_t now)
{
+ su_timer_queue_t *timers;
+
su_duration_t tout;
- t = timers_first(t);
+ if (!t)
+ return SU_DURATION_MAX;
+
+ timers = su_task_timers(t->sut_task);
+
+ t = timers ? timers_get(timers[0], 1) : NULL;
if (!t)
return SU_DURATION_MAX;
@@ -573,23 +592,29 @@
*/
int su_timer_reset_all(su_timer_queue_t *timers, su_task_r task)
{
- su_timer_t *t, *t_next;
+ size_t i;
int n = 0;
- if (!timers || !*timers)
+ if (!timers)
return 0;
- for (t = timers_first(*timers); t; t = t_next) {
- t_next = timers_succ(t);
+ timers_sort(timers[0]);
+
+ for (i = timers_used(timers[0]); i > 0; i--) {
+ su_timer_t *t = timers_get(timers[0], i);
if (su_task_cmp(task, t->sut_task))
continue;
- n++;
- timers_remove(timers, t);
+ timers_remove(timers[0], i)->sut_heap_index = 0;
+
su_free(NULL, t);
+ n++;
}
+ if (!timers_used(timers[0]))
+ free(timers->private), timers->private = NULL;
+
return n;
}
@@ -605,3 +630,4 @@
{
return t ? su_task_root(t->sut_task) : NULL;
}
+
1
0
[commit] r11847 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/nua
by FreeSWITCH SVN 11 Feb '09
by FreeSWITCH SVN 11 Feb '09
11 Feb '09
Author: mikej
Date: Wed Feb 11 11:14:06 2009
New Revision: 11847
Log:
Wed Jan 28 13:34:54 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* nua_dialog.c: avoid debug output with nua_dialog_usage_set_refresh_at()
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Wed Feb 11 11:14:06 2009
@@ -1 +1 @@
-Wed Feb 11 11:13:29 CST 2009
+Wed Feb 11 11:13:59 CST 2009
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c Wed Feb 11 11:14:06 2009
@@ -543,7 +543,7 @@
du->du_refquested = now;
- nua_dialog_usage_set_refresh_at(du, target);
+ du->du_refresh = target;
}
/** Set absolute refresh time */
1
0
Author: mikej
Date: Wed Feb 11 11:13:36 2009
New Revision: 11846
Log:
Mon Jan 26 09:45:30 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* RELEASE: msg_multipart_t::mp_len from usize_t to unsigned
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/RELEASE
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Wed Feb 11 11:13:36 2009
@@ -1 +1 @@
-Wed Feb 11 11:12:10 CST 2009
+Wed Feb 11 11:13:29 CST 2009
Modified: freeswitch/trunk/libs/sofia-sip/RELEASE
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/RELEASE (original)
+++ freeswitch/trunk/libs/sofia-sip/RELEASE Wed Feb 11 11:13:36 2009
@@ -25,6 +25,9 @@
libsofia-sip-ua:
- **template**: Added foobar() function (sofia-sip/foobar.h).
+- The mp_len type was changed from usize_t to unsigned.
+ The change is binary-incompatible on 64-bit platforms when compiled with
+ the configure opetion --disable-size-compat
- This release is ABI/API compatible with applications linked against
any 1.12.x release. However, applications built against this release won't
work against an older library. The ABI has been tested with the nua module
1
0
[commit] r11845 - freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip
by FreeSWITCH SVN 11 Feb '09
by FreeSWITCH SVN 11 Feb '09
11 Feb '09
Author: mikej
Date: Wed Feb 11 11:13:16 2009
New Revision: 11845
Log:
Wed Jan 21 10:38:08 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* msg_multipart_s: fixed mp_len type
The msg_multipart_s should follow msg_pub_s layout.
Modified:
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_mime.h
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_mime.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_mime.h (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_mime.h Wed Feb 11 11:13:16 2009
@@ -163,7 +163,7 @@
msg_multipart_t *mp_next; /**< Next part in multipart body */
/* Preamble for this part */
char *mp_data; /**< Boundary string. */
- usize_t mp_len; /**< Length of boundary (mp_data).*/
+ unsigned mp_len; /**< Length of boundary (mp_data).*/
unsigned mp_flags;
msg_error_t *mp_error;
1
0
[commit] r11844 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/nua libsofia-sip-ua/sresolv
by FreeSWITCH SVN 11 Feb '09
by FreeSWITCH SVN 11 Feb '09
11 Feb '09
Author: mikej
Date: Wed Feb 11 11:12:33 2009
New Revision: 11844
Log:
Fri Jan 23 11:13:41 CST 2009 Pekka Pessi <first.last(a)nokia.com>
* sresolv: caching SRES_RECORD_ERR in case a CNAME is returned, too
Tracing the CNAMEs when doing cache lookups.
Added:
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/check_simple.c
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/example.com
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/sresolv/test_sresolv.c
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Wed Feb 11 11:12:33 2009
@@ -1 +1 @@
-Wed Feb 11 11:08:29 CST 2009
+Wed Feb 11 11:12:10 CST 2009
Added: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/check_simple.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/check_simple.c Wed Feb 11 11:12:33 2009
@@ -0,0 +1,522 @@
+/*
+ * This file is part of the Sofia-SIP package
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * Contact: Pekka Pessi <pekka.pessi(a)nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/**@CFILE check_events.c
+ *
+ * @brief NUA module tests for SIP events
+ *
+ * @author Pekka Pessi <Pekka.Pessi(a)nokia.com>
+ *
+ * @copyright (C) 2008 Nokia Corporation.
+ */
+
+#include "config.h"
+
+#include "check_nua.h"
+
+#include "test_s2.h"
+
+#include <sofia-sip/sip_status.h>
+#include <sofia-sip/sip_header.h>
+#include <sofia-sip/soa.h>
+#include <sofia-sip/su_tagarg.h>
+#include <sofia-sip/su_string.h>
+#include <sofia-sip/su_tag_io.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+/* define XXX as 1 in order to see all failing test cases */
+#ifndef XXX
+#define XXX (0)
+#endif
+
+/* ====================================================================== */
+
+static nua_t *nua;
+static soa_session_t *soa = NULL;
+static struct dialog *dialog = NULL;
+
+#define CRLF "\r\n"
+
+void s2_dialog_setup(void)
+{
+ nua = s2_nua_setup("simple",
+ SIPTAG_ORGANIZATION_STR("Pussy Galore's Flying Circus"),
+ NUTAG_OUTBOUND("no-options-keepalive, no-validate"),
+ TAG_END());
+
+ soa = soa_create(NULL, s2->root, NULL);
+
+ fail_if(!soa);
+
+ soa_set_params(soa,
+ SOATAG_USER_SDP_STR("m=audio 5008 RTP/AVP 8 0" CRLF
+ "m=video 5010 RTP/AVP 34" CRLF),
+ TAG_END());
+
+ dialog = su_home_new(sizeof *dialog); fail_if(!dialog);
+
+ s2_register_setup();
+}
+
+void s2_dialog_teardown(void)
+{
+ s2_teardown_started("simple");
+
+ s2_register_teardown();
+
+ nua_shutdown(nua);
+
+ fail_unless(s2_check_event(nua_r_shutdown, 200));
+
+ s2_nua_teardown();
+}
+
+
+static char const presence_open[] =
+ "<?xml version='1.0' encoding='UTF-8'?>\n"
+ "<presence xmlns='urn:ietf:params:xml:ns:cpim-pidf' \n"
+ " entity='pres:bob@example.org'>\n"
+ " <tuple id='ksac9udshce'>\n"
+ " <status><basic>open</basic></status>\n"
+ " <contact priority='1.0'>sip:bob@example.org</contact>\n"
+ " </tuple>\n"
+ "</presence>\n";
+
+static char const presence_closed[] =
+ "<?xml version='1.0' encoding='UTF-8'?>\n"
+ "<presence xmlns='urn:ietf:params:xml:ns:cpim-pidf' \n"
+ " entity='pres:bob@example.org'>\n"
+ " <tuple id='ksac9udshce'>\n"
+ " <status><basic>closed</basic></status>\n"
+ " </tuple>\n"
+ "</presence>\n";
+
+static char const *event_type = "presence";
+static char const *event_mime_type = "application/pidf+xml";
+static char const *event_state = presence_open;
+static char const *subscription_state = "active;expires=600";
+
+static struct event *
+respond_to_subscribe(struct message *subscribe,
+ nua_event_t expect_event,
+ enum nua_substate expect_substate,
+ int status, char const *phrase,
+ tag_type_t tag, tag_value_t value, ...)
+{
+ struct event *event;
+ ta_list ta;
+
+ ta_start(ta, tag, value);
+ s2_respond_to(subscribe, dialog, status, phrase,
+ ta_tags(ta));
+ ta_end(ta);
+
+ event = s2_wait_for_event(expect_event, status); fail_if(!event);
+ fail_unless(s2_check_substate(event, expect_substate));
+ return event;
+}
+
+static struct event *
+notify_to_nua(enum nua_substate expect_substate,
+ tag_type_t tag, tag_value_t value, ...)
+{
+ struct event *event;
+ struct message *response;
+ ta_list ta;
+
+ ta_start(ta, tag, value);
+ fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
+ SIPTAG_CONTENT_TYPE_STR(event_mime_type),
+ SIPTAG_PAYLOAD_STR(event_state),
+ ta_tags(ta)));
+ ta_end(ta);
+
+ response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
+ fail_if(!response);
+ s2_free_message(response);
+
+ event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
+ fail_unless(s2_check_substate(event, expect_substate));
+
+ return event;
+}
+
+static int send_notify_before_response = 0;
+
+static struct event *
+subscription_by_nua(nua_handle_t *nh,
+ enum nua_substate current,
+ tag_type_t tag, tag_value_t value, ...)
+{
+ struct message *subscribe;
+ struct event *notify, *event;
+ ta_list ta;
+ enum nua_substate substate = nua_substate_active;
+ char const *substate_str = subscription_state;
+ char const *expires = "600";
+
+ subscribe = s2_wait_for_request(SIP_METHOD_SUBSCRIBE);
+ if (event_type)
+ fail_if(!subscribe->sip->sip_event ||
+ strcmp(event_type, subscribe->sip->sip_event->o_type));
+
+ if (subscribe->sip->sip_expires && subscribe->sip->sip_expires->ex_delta == 0) {
+ substate = nua_substate_terminated;
+ substate_str = "terminated;reason=timeout";
+ expires = "0";
+ }
+
+ ta_start(ta, tag, value);
+
+ if (send_notify_before_response) {
+ s2_save_uas_dialog(dialog, subscribe->sip);
+ notify = notify_to_nua(substate,
+ SIPTAG_EVENT(subscribe->sip->sip_event),
+ SIPTAG_SUBSCRIPTION_STATE_STR(substate_str),
+ ta_tags(ta));
+ event = respond_to_subscribe(subscribe, nua_r_subscribe, substate,
+ SIP_200_OK,
+ SIPTAG_EXPIRES_STR(expires),
+ TAG_END());
+ s2_free_event(event);
+ }
+ else {
+ event = respond_to_subscribe(subscribe, nua_r_subscribe, current,
+ SIP_202_ACCEPTED,
+ SIPTAG_EXPIRES_STR(expires),
+ TAG_END());
+ s2_free_event(event);
+ notify = notify_to_nua(substate,
+ SIPTAG_EVENT(subscribe->sip->sip_event),
+ SIPTAG_SUBSCRIPTION_STATE_STR(substate_str),
+ ta_tags(ta));
+ }
+
+ s2_free_message(subscribe);
+
+ return notify;
+}
+
+static void
+unsubscribe_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
+{
+ struct message *subscribe, *response;
+ struct event *event;
+
+ nua_unsubscribe(nh, TAG_END());
+ subscribe = s2_wait_for_request(SIP_METHOD_SUBSCRIBE);
+
+ s2_respond_to(subscribe, dialog, SIP_200_OK, SIPTAG_EXPIRES_STR("0"), TAG_END());
+
+ event = s2_wait_for_event(nua_r_unsubscribe, 200); fail_if(!event);
+ fail_unless(s2_check_substate(event, nua_substate_active));
+ s2_free_event(event);
+
+ fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
+ SIPTAG_EVENT(subscribe->sip->sip_event),
+ SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=tiemout"),
+ SIPTAG_CONTENT_TYPE_STR(event_mime_type),
+ SIPTAG_PAYLOAD_STR(event_state),
+ TAG_END()));
+
+ event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
+ fail_unless(s2_check_substate(event, nua_substate_terminated));
+ s2_free_event(event);
+
+ response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
+ fail_if(!response);
+ s2_free_message(response); s2_free_message(subscribe);
+}
+
+/* ====================================================================== */
+/* 6 - Subscribe/notify */
+
+START_TEST(subscribe_6_1_1)
+{
+ nua_handle_t *nh;
+ struct event *notify;
+ s2_case("6.1.1", "Basic subscription",
+ "NUA sends SUBSCRIBE, waits for NOTIFY, sends un-SUBSCRIBE");
+
+ nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
+ nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END());
+ notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
+ s2_free_event(notify);
+ unsubscribe_by_nua(nh, TAG_END());
+ nua_handle_destroy(nh);
+}
+END_TEST
+
+START_TEST(subscribe_6_1_2)
+{
+ nua_handle_t *nh;
+ struct message *subscribe, *response;
+ struct event *notify, *event;
+
+ s2_case("6.1.2", "Basic subscription with refresh",
+ "NUA sends SUBSCRIBE, waits for NOTIFY, "
+ "sends re-SUBSCRIBE, waits for NOTIFY, "
+ "sends un-SUBSCRIBE");
+
+ send_notify_before_response = 1;
+
+ nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
+ nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END());
+ notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
+ s2_free_event(notify);
+
+ /* Wait for refresh */
+ s2_fast_forward(600);
+ subscribe = s2_wait_for_request(SIP_METHOD_SUBSCRIBE);
+ s2_respond_to(subscribe, dialog, SIP_200_OK,
+ SIPTAG_EXPIRES_STR("600"),
+ TAG_END());
+
+ event = s2_wait_for_event(nua_r_subscribe, 200); fail_if(!event);
+ fail_unless(s2_check_substate(event, nua_substate_active));
+ s2_free_event(event);
+
+ fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
+ SIPTAG_EVENT(subscribe->sip->sip_event),
+ SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=600"),
+ SIPTAG_CONTENT_TYPE_STR(event_mime_type),
+ SIPTAG_PAYLOAD_STR(event_state),
+ TAG_END()));
+ event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
+ fail_unless(s2_check_substate(event, nua_substate_active));
+ s2_free_event(event);
+ response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
+ fail_if(!response);
+ s2_free_message(response);
+
+ unsubscribe_by_nua(nh, TAG_END());
+
+ nua_handle_destroy(nh);
+}
+END_TEST
+
+START_TEST(subscribe_6_1_3)
+{
+ nua_handle_t *nh;
+ struct message *response;
+ struct event *notify, *event;
+
+ s2_case("6.1.3", "Subscription terminated by notifier",
+ "NUA sends SUBSCRIBE, waits for NOTIFY, "
+ "gets NOTIFY terminating the subscription,");
+
+ nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
+ nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END());
+ notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
+ s2_free_event(notify);
+
+ fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
+ SIPTAG_EVENT_STR(event_type),
+ SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
+ TAG_END()));
+ event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
+ fail_unless(s2_check_substate(event, nua_substate_terminated));
+ s2_free_event(event);
+ response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
+ fail_if(!response);
+ s2_free_message(response);
+
+ nua_handle_destroy(nh);
+}
+END_TEST
+
+START_TEST(subscribe_6_1_4)
+{
+ nua_handle_t *nh;
+ struct message *response;
+ struct event *notify, *event;
+
+ s2_case("6.1.4", "Subscription terminated by notifier, re-established",
+ "NUA sends SUBSCRIBE, waits for NOTIFY, "
+ "gets NOTIFY terminating the subscription,");
+
+ nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
+ nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END());
+ notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
+ s2_free_event(notify);
+
+ fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
+ SIPTAG_EVENT_STR(event_type),
+ SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=deactivated"),
+ TAG_END()));
+ event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
+ fail_unless(s2_check_substate(event, nua_substate_embryonic));
+ s2_free_event(event);
+ response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
+ fail_if(!response);
+ s2_free_message(response);
+
+ su_home_unref((void *)dialog), dialog = su_home_new(sizeof *dialog); fail_if(!dialog);
+
+ s2_fast_forward(5);
+ /* nua re-establishes the subscription */
+ notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
+ s2_free_event(notify);
+
+ /* Unsubscribe with nua_subscribe() Expires: 0 */
+ nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END());
+ notify = subscription_by_nua(nh, nua_substate_active, TAG_END());
+ s2_free_event(notify);
+
+ nua_handle_destroy(nh);
+}
+END_TEST
+
+TCase *subscribe_tcase(void)
+{
+ TCase *tc = tcase_create("6.1 - Basic SUBSCRIBE_");
+ tcase_add_checked_fixture(tc, s2_dialog_setup, s2_dialog_teardown);
+ {
+ tcase_add_test(tc, subscribe_6_1_1);
+ tcase_add_test(tc, subscribe_6_1_2);
+ tcase_add_test(tc, subscribe_6_1_3);
+ tcase_add_test(tc, subscribe_6_1_4);
+ }
+ return tc;
+}
+
+START_TEST(fetch_6_2_1)
+{
+ nua_handle_t *nh;
+ struct event *notify;
+
+ s2_case("6.2.1", "Event fetch - NOTIFY after 202",
+ "NUA sends SUBSCRIBE with Expires 0, waits for NOTIFY");
+
+ nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
+ nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END());
+ notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
+ s2_check_substate(notify, nua_substate_terminated);
+ s2_free_event(notify);
+ nua_handle_destroy(nh);
+}
+END_TEST
+
+START_TEST(fetch_6_2_2)
+{
+ nua_handle_t *nh;
+ struct event *notify;
+
+ s2_case("6.2.2", "Event fetch - NOTIFY before 200",
+ "NUA sends SUBSCRIBE with Expires 0, waits for NOTIFY");
+
+ send_notify_before_response = 1;
+
+ nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
+ nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END());
+ notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
+ s2_check_substate(notify, nua_substate_terminated);
+ s2_free_event(notify);
+ nua_handle_destroy(nh);
+}
+END_TEST
+
+START_TEST(fetch_6_2_3)
+{
+ nua_handle_t *nh;
+ struct message *subscribe;
+ struct event *event;
+
+ s2_case("6.2.3", "Event fetch - no NOTIFY",
+ "NUA sends SUBSCRIBE with Expires 0, waits for NOTIFY, times out");
+
+ nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
+ nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END());
+ subscribe = s2_wait_for_request(SIP_METHOD_SUBSCRIBE);
+ s2_respond_to(subscribe, dialog, SIP_202_ACCEPTED,
+ SIPTAG_EXPIRES_STR("0"), TAG_END());
+ s2_free_message(subscribe);
+
+ event = s2_wait_for_event(nua_r_subscribe, 202); fail_if(!event);
+ fail_unless(s2_check_substate(event, nua_substate_embryonic));
+ s2_free_event(event);
+
+ s2_fast_forward(600);
+
+ event = s2_wait_for_event(nua_i_notify, 408); fail_if(!event);
+ fail_unless(s2_check_substate(event, nua_substate_terminated));
+ s2_free_event(event);
+
+ nua_handle_destroy(nh);
+}
+END_TEST
+
+
+TCase *fetch_tcase(void)
+{
+ TCase *tc = tcase_create("6.2 - Event fetch");
+ tcase_add_checked_fixture(tc, s2_dialog_setup, s2_dialog_teardown);
+ {
+ tcase_add_test(tc, fetch_6_2_1);
+ tcase_add_test(tc, fetch_6_2_2);
+ tcase_add_test(tc, fetch_6_2_3);
+ }
+ return tc;
+}
+
+/* ====================================================================== */
+
+/* Test case template */
+
+START_TEST(empty)
+{
+ s2_case("0.0.0", "Empty test case",
+ "Detailed explanation for empty test case.");
+
+ tport_set_params(s2->master, TPTAG_LOG(1), TAG_END());
+ s2_setup_logs(7);
+ s2_setup_logs(0);
+ tport_set_params(s2->master, TPTAG_LOG(0), TAG_END());
+}
+
+END_TEST
+
+static TCase *empty_tcase(void)
+{
+ TCase *tc = tcase_create("0 - Empty");
+ tcase_add_checked_fixture(tc, s2_dialog_setup, s2_dialog_teardown);
+ tcase_add_test(tc, empty);
+
+ return tc;
+}
+
+/* ====================================================================== */
+
+void check_simple_cases(Suite *suite)
+{
+ suite_add_tcase(suite, subscribe_tcase());
+ suite_add_tcase(suite, fetch_tcase());
+
+ if (0) /* Template */
+ suite_add_tcase(suite, empty_tcase());
+}
+
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/example.com
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/example.com (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/example.com Wed Feb 11 11:12:33 2009
@@ -42,6 +42,11 @@
SRV 4 50 5051 sip02
SRV 5 10 5061 sip01
+cloop CNAME cloop0
+cloop0 CNAME cloop1
+cloop1 CNAME cloop2
+cloop2 CNAME cloop0
+
sip CNAME sip00
subnet A6 0 3ff0:0::
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 Wed Feb 11 11:12:33 2009
@@ -495,7 +495,9 @@
static char const *sres_toplevel(char buf[], size_t bsize, char const *domain);
-static sres_record_t *sres_create_record(sres_resolver_t *, sres_message_t *m);
+static sres_record_t *sres_create_record(sres_resolver_t *,
+ sres_message_t *m,
+ int nth);
static sres_record_t *sres_init_rr_soa(sres_cache_t *cache,
sres_soa_record_t *,
@@ -3539,7 +3541,7 @@
total = errorcount + m->m_ancount + m->m_nscount + m->m_arcount;
- answers = su_zalloc(chome, (total + 1) * sizeof answers[0]);
+ answers = su_zalloc(chome, (total + 2) * sizeof answers[0]);
if (!answers)
return -1;
@@ -3548,7 +3550,7 @@
if (i < errorcount)
rr = error = sres_create_error_rr(res->res_cache, query, err);
else
- rr = sres_create_record(res, m);
+ rr = sres_create_record(res, m, i - errorcount);
if (!rr) {
SU_DEBUG_5(("sres_create_record: %s\n", m->m_error));
@@ -3565,12 +3567,31 @@
}
if (i < total) {
+ SU_DEBUG_5(("sres_decode_msg: %s\n", "less records than promised"));
for (i = 0; i < total; i++)
sres_cache_free_record(res->res_cache, answers[i]);
su_free(chome, answers);
return -1;
}
+ if (m->m_ancount > 0 && errorcount == 0 && query->q_type < sres_qtype_tsig) {
+ char b0[8], b1[8];
+ for (i = 0; i < m->m_ancount; i++) {
+ if (query->q_type == answers[i]->sr_type)
+ break;
+ }
+
+ if (i == m->m_ancount) {
+ /* The queried request was not found. CNAME? */
+ SU_DEBUG_5(("sres_decode_msg: sent query %s, got %s\n",
+ sres_record_type(query->q_type, b0),
+ sres_record_type(answers[0]->sr_type, b1)));
+ rr = sres_create_error_rr(res->res_cache, query, err = SRES_RECORD_ERR);
+ memmove(answers + 1, answers, (sizeof answers[0]) * total++);
+ answers[errorcount++] = rr;
+ }
+ }
+
for (i = 0; i < total; i++) {
rr = answers[i];
@@ -3591,7 +3612,7 @@
static
sres_record_t *
-sres_create_record(sres_resolver_t *res, sres_message_t *m)
+sres_create_record(sres_resolver_t *res, sres_message_t *m, int nth)
{
sres_cache_t *cache = res->res_cache;
sres_record_t *sr, sr0[1];
@@ -3614,7 +3635,11 @@
name[len] = 0;
- SU_DEBUG_9(("RR received %s %s %s %d rdlen=%d\n", name,
+ SU_DEBUG_9(("%s RR received %s %s %s %d rdlen=%d\n",
+ nth < m->m_ancount ? "ANSWER" :
+ nth < m->m_ancount + m->m_nscount ? "AUTHORITY" :
+ "ADDITIONAL",
+ name,
sres_record_type(sr->sr_type, btype),
sres_record_class(sr->sr_class, bclass),
sr->sr_ttl, sr->sr_rdlen));
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 Wed Feb 11 11:12:33 2009
@@ -169,15 +169,98 @@
su_home_unref(cache->cache_home);
}
+struct frame {
+ struct frame *previous;
+ char const *domain;
+};
+
+/** Count or get matching records from cache */
+static int
+sres_cache_get0(sres_htable_t *htable,
+ sres_rr_hash_entry_t **iter,
+ uint16_t type,
+ char const *domain,
+ time_t now,
+ sres_record_t **cached,
+ int len,
+ struct frame *previous)
+{
+ sres_cname_record_t *cname = NULL;
+ int dcount = 0, derrorcount = 0, ccount = 0;
+
+ for (; iter && *iter; iter = sres_htable_next(htable, iter)) {
+ sres_record_t *rr = (*iter)->rr;
+
+ if (rr == NULL)
+ continue;
+ if (now > (*iter)->rr_expires)
+ continue;
+ if (rr->sr_name == NULL)
+ continue;
+ if (!su_casematch(rr->sr_name, domain))
+ continue;
+
+ if (rr->sr_type == type || type == sres_qtype_any) {
+ if (rr->sr_status == SRES_RECORD_ERR && type == sres_qtype_any)
+ continue;
+ if (cached) {
+ if (dcount >= len)
+ return -1;
+ cached[dcount] = rr, rr->sr_refcount++;
+ }
+ dcount++;
+ if (rr->sr_status)
+ derrorcount++;
+ }
+
+ if (type != sres_type_cname && rr->sr_type == sres_type_cname) {
+ if (rr->sr_status == 0)
+ cname = rr->sr_cname;
+ }
+ }
+
+ if (cname && dcount == derrorcount) {
+ /* Nothing found, trace CNAMEs */
+ struct frame *f, frame = { previous, domain };
+ unsigned hash = sres_hash_key(domain = cname->cn_cname);
+
+ if (cached) {
+ if (dcount >= len)
+ return -1;
+ cached[dcount] = (sres_record_t *)cname;
+ cname->cn_record->r_refcount++;
+ }
+ dcount++;
+
+ /* Check for cname loops */
+ for (f = previous; f; f = f->previous) {
+ if (su_casematch(domain, f->domain))
+ break;
+ }
+
+ if (f == NULL) {
+ ccount = sres_cache_get0(htable, sres_htable_hash(htable, hash),
+ type, domain, now,
+ cached ? cached + dcount : NULL,
+ cached ? len - dcount : 0,
+ &frame);
+ }
+ if (ccount < 0)
+ return ccount;
+ }
+
+ return dcount + ccount;
+}
+
/** Get a list of matching records from cache. */
int sres_cache_get(sres_cache_t *cache,
uint16_t type,
char const *domain,
sres_record_t ***return_cached)
{
- sres_record_t **result = NULL, *rr = NULL;
- sres_rr_hash_entry_t **rr_iter, **rr_iter2;
- int result_size, rr_count = 0;
+ sres_record_t **result = NULL;
+ sres_rr_hash_entry_t **slot;
+ int result_size, i, j;
unsigned hash;
time_t now;
char b[8];
@@ -198,28 +281,16 @@
time(&now);
/* First pass: just count the number of rr:s for array allocation */
- rr_iter2 = sres_htable_hash(cache->cache_hash, hash);
-
- /* Find the domain records from the hash table */
- for (rr_iter = rr_iter2;
- rr_iter && *rr_iter;
- rr_iter = sres_htable_next(cache->cache_hash, rr_iter)) {
- rr = (*rr_iter)->rr;
-
- if (rr != NULL &&
- now <= (*rr_iter)->rr_expires &&
- (type == sres_qtype_any || rr->sr_type == type) &&
- rr->sr_name != NULL &&
- su_casematch(rr->sr_name, domain))
- rr_count++;
- }
+ slot = sres_htable_hash(cache->cache_hash, hash);
- if (rr_count == 0) {
+ i = sres_cache_get0(cache->cache_hash, slot, type, domain, now,
+ NULL, 0, NULL);
+ if (i <= 0) {
UNLOCK(cache);
return 0;
}
- result_size = (sizeof *result) * (rr_count + 1);
+ result_size = (sizeof *result) * (i + 1);
result = su_zalloc(cache->cache_home, result_size);
if (result == NULL) {
UNLOCK(cache);
@@ -227,35 +298,30 @@
}
/* Second pass: add the rr pointers to the allocated array */
-
- for (rr_iter = rr_iter2, rr_count = 0;
- rr_iter && *rr_iter;
- rr_iter = sres_htable_next(cache->cache_hash, rr_iter)) {
- rr = (*rr_iter)->rr;
-
- if (rr != NULL &&
- now <= (*rr_iter)->rr_expires &&
- (type == sres_qtype_any || rr->sr_type == type) &&
- rr->sr_name != NULL &&
- su_casematch(rr->sr_name, domain)) {
- SU_DEBUG_9(("rr found in cache: %s %02d\n",
- rr->sr_name, rr->sr_type));
-
- result[rr_count++] = rr;
- rr->sr_refcount++;
+ j = sres_cache_get0(cache->cache_hash, slot, type, domain, now,
+ result, i, NULL);
+ if (i != j) {
+ /* Uh-oh. */
+ SU_DEBUG_9(("%s(%p, %s, \"%s\") got %d != %d\n", "sres_cache_get",
+ (void *)cache, sres_record_type(type, b), domain, i, j));
+ for (i = 0; i < result_size; i++) {
+ if (result[i])
+ result[i]->sr_refcount--;
}
+ su_free(cache->cache_home, result);
+ return 0;
}
- result[rr_count] = NULL;
+ result[i] = NULL;
UNLOCK(cache);
SU_DEBUG_9(("%s(%p, %s, \"%s\") returned %d entries\n", "sres_cache_get",
- (void *)cache, sres_record_type(type, b), domain, rr_count));
+ (void *)cache, sres_record_type(type, b), domain, i));
*return_cached = result;
- return rr_count;
+ return i;
}
sres_record_t *
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c Wed Feb 11 11:12:33 2009
@@ -90,6 +90,10 @@
#include <signal.h>
#endif
+#include <sofia-sip/su_log.h>
+
+extern su_log_t sresolv_log[];
+
char const name[] = "test_sresolv";
struct sres_context_s
@@ -982,24 +986,133 @@
int test_cname(sres_context_t *ctx)
{
sres_resolver_t *res = ctx->resolver;
- sres_record_t **result;
- const sres_cname_record_t *rr;
+ sres_record_t **result, *sr;
+ const sres_cname_record_t *cn;
char const *domain = "sip.example.com";
BEGIN();
+ TEST_1(sres_query(res, test_answer, ctx, sres_type_naptr, domain));
+ TEST_RUN(ctx);
+
+ TEST_1(result = ctx->result);
+ TEST_1(sr = result[0]);
+ TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR);
+ TEST_1(cn = result[1]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "sip00.example.com.");
+
+ sres_free_answers(res, ctx->result), ctx->result = NULL;
+
+ TEST_1(result = sres_cached_answers(res, sres_type_naptr, domain));
+ TEST_1(sr = result[0]);
+ TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR);
+ TEST_1(cn = result[1]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "sip00.example.com.");
+
+ sres_free_answers(res, result), ctx->result = NULL;
+
+ TEST_1(result = sres_cached_answers(res, sres_qtype_any, domain));
+ TEST_1(cn = result[0]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "sip00.example.com.");
+ /* We might have A record, or then not */
+
+ sres_free_answers(res, result), ctx->result = NULL;
+
+ TEST_1(sres_query(res, test_answer, ctx, sres_type_a, domain));
+ TEST_RUN(ctx);
+
+ TEST_1(result = ctx->result);
+ TEST_1(cn = result[0]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "sip00.example.com.");
+ TEST_1(sr = result[1]);
+ TEST(sr->sr_record->r_class, sres_class_in);
+ TEST(sr->sr_record->r_type, sres_type_a);
+
+ sres_free_answers(res, ctx->result), ctx->result = NULL;
+
+ TEST_1(result = sres_cached_answers(res, sres_type_a, domain));
+ TEST_1(cn = result[0]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "sip00.example.com.");
+ TEST_1(sr = result[1]);
+ TEST(sr->sr_record->r_class, sres_class_in);
+ TEST(sr->sr_record->r_type, sres_type_a);
+
+ sres_free_answers(res, result);
+
+ domain = "cloop.example.com";
+
TEST_1(sres_query(res, test_answer, ctx, sres_type_a, domain));
TEST_RUN(ctx);
TEST_1(result = ctx->result);
- TEST_1(rr = result[0]->sr_cname);
- TEST(rr->cn_record->r_class, sres_class_in);
- TEST(rr->cn_record->r_type, sres_type_cname);
- TEST(rr->cn_record->r_ttl, 60);
- TEST_S(rr->cn_cname, "sip00.example.com.");
+ TEST_1(sr = result[0]);
+ TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR);
+ TEST_1(cn = result[1]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "cloop0.example.com.");
+ TEST_1(cn = result[2]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "cloop1.example.com.");
+ TEST_1(cn = result[3]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "cloop2.example.com.");
+ TEST_1(cn = result[4]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "cloop0.example.com.");
+ TEST_1(result[5] == NULL);
sres_free_answers(res, ctx->result), ctx->result = NULL;
+ TEST_1(result = sres_cached_answers(res, sres_type_a, domain));
+ TEST_1(sr = result[0]);
+ TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR);
+ TEST_1(cn = result[1]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "cloop0.example.com.");
+ TEST_1(cn = result[2]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "cloop1.example.com.");
+ TEST_1(cn = result[3]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "cloop2.example.com.");
+ TEST_1(cn = result[4]->sr_cname);
+ TEST(cn->cn_record->r_class, sres_class_in);
+ TEST(cn->cn_record->r_type, sres_type_cname);
+ TEST(cn->cn_record->r_ttl, 60);
+ TEST_S(cn->cn_cname, "cloop0.example.com.");
+ TEST_1(result[5] == NULL);
+
+ sres_free_answers(res, result);
+
END();
}
@@ -1892,10 +2005,6 @@
exit(exitcode);
}
-#include <sofia-sip/su_log.h>
-
-extern su_log_t sresolv_log[];
-
int main(int argc, char **argv)
{
int i;
1
0