Set svn:eol-style property

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@65 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjlib/src/pj/addr_resolv_linux_kernel.c b/pjlib/src/pj/addr_resolv_linux_kernel.c
index fe70acb..d6a4dcc 100644
--- a/pjlib/src/pj/addr_resolv_linux_kernel.c
+++ b/pjlib/src/pj/addr_resolv_linux_kernel.c
@@ -1,25 +1,25 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/addr_resolv.h>

-

-PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *hostname, pj_hostent *phe)

-{

-    return -1;

-}

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/addr_resolv.h>
+
+PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *hostname, pj_hostent *phe)
+{
+    return -1;
+}
+
diff --git a/pjlib/src/pj/addr_resolv_sock.c b/pjlib/src/pj/addr_resolv_sock.c
index e4493b2..9b9eb6d 100644
--- a/pjlib/src/pj/addr_resolv_sock.c
+++ b/pjlib/src/pj/addr_resolv_sock.c
@@ -1,51 +1,51 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/addr_resolv.h>

-#include <pj/assert.h>

-#include <pj/string.h>

-#include <pj/compat/socket.h>

-#include <pj/errno.h>

-

-

-PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *hostname, pj_hostent *phe)

-{

-    struct hostent *he;

-    char copy[PJ_MAX_HOSTNAME];

-

-    pj_assert(hostname && hostname ->slen < PJ_MAX_HOSTNAME);

-    

-    if (hostname->slen >= PJ_MAX_HOSTNAME)

-	return PJ_ENAMETOOLONG;

-

-    pj_memcpy(copy, hostname->ptr, hostname->slen);

-    copy[ hostname->slen ] = '\0';

-

-    he = gethostbyname(copy);

-    if (!he)

-	return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());

-

-    phe->h_name = he->h_name;

-    phe->h_aliases = he->h_aliases;

-    phe->h_addrtype = he->h_addrtype;

-    phe->h_length = he->h_length;

-    phe->h_addr_list = he->h_addr_list;

-

-    return PJ_SUCCESS;

-}

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/addr_resolv.h>
+#include <pj/assert.h>
+#include <pj/string.h>
+#include <pj/compat/socket.h>
+#include <pj/errno.h>
+
+
+PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *hostname, pj_hostent *phe)
+{
+    struct hostent *he;
+    char copy[PJ_MAX_HOSTNAME];
+
+    pj_assert(hostname && hostname ->slen < PJ_MAX_HOSTNAME);
+    
+    if (hostname->slen >= PJ_MAX_HOSTNAME)
+	return PJ_ENAMETOOLONG;
+
+    pj_memcpy(copy, hostname->ptr, hostname->slen);
+    copy[ hostname->slen ] = '\0';
+
+    he = gethostbyname(copy);
+    if (!he)
+	return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
+
+    phe->h_name = he->h_name;
+    phe->h_aliases = he->h_aliases;
+    phe->h_addrtype = he->h_addrtype;
+    phe->h_length = he->h_length;
+    phe->h_addr_list = he->h_addr_list;
+
+    return PJ_SUCCESS;
+}
+
diff --git a/pjlib/src/pj/array.c b/pjlib/src/pj/array.c
index 59854a1..2afe8fe 100644
--- a/pjlib/src/pj/array.c
+++ b/pjlib/src/pj/array.c
@@ -1,70 +1,70 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/array.h>

-#include <pj/string.h>

-#include <pj/assert.h>

-#include <pj/errno.h>

-

-PJ_DEF(void) pj_array_insert( void *array,

-			      unsigned elem_size,

-			      unsigned count,

-			      unsigned pos,

-			      const void *value)

-{

-    if (count && pos < count-1) {

-	pj_memmove( (char*)array + (pos+1)*elem_size,

-		    (char*)array + pos*elem_size,

-		    (count-pos)*elem_size);

-    }

-    pj_memmove((char*)array + pos*elem_size, value, elem_size);

-}

-

-PJ_DEF(void) pj_array_erase( void *array,

-			     unsigned elem_size,

-			     unsigned count,

-			     unsigned pos)

-{

-    pj_assert(count != 0);

-    if (pos < count-1) {

-	pj_memmove( (char*)array + pos*elem_size,

-		    (char*)array + (pos+1)*elem_size,

-		    (count-pos-1)*elem_size);

-    }

-}

-

-PJ_DEF(pj_status_t) pj_array_find( const void *array, 

-				   unsigned elem_size, 

-				   unsigned count, 

-				   pj_status_t (*matching)(const void *value),

-				   void **result)

-{

-    unsigned i;

-    const char *char_array = array;

-    for (i=0; i<count; ++i) {

-	if ( (*matching)(char_array) == PJ_SUCCESS) {

-	    if (result) {

-		*result = (void*)char_array;

-	    }

-	    return PJ_SUCCESS;

-	}

-	char_array += elem_size;

-    }

-    return PJ_ENOTFOUND;

-}

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/array.h>
+#include <pj/string.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+
+PJ_DEF(void) pj_array_insert( void *array,
+			      unsigned elem_size,
+			      unsigned count,
+			      unsigned pos,
+			      const void *value)
+{
+    if (count && pos < count-1) {
+	pj_memmove( (char*)array + (pos+1)*elem_size,
+		    (char*)array + pos*elem_size,
+		    (count-pos)*elem_size);
+    }
+    pj_memmove((char*)array + pos*elem_size, value, elem_size);
+}
+
+PJ_DEF(void) pj_array_erase( void *array,
+			     unsigned elem_size,
+			     unsigned count,
+			     unsigned pos)
+{
+    pj_assert(count != 0);
+    if (pos < count-1) {
+	pj_memmove( (char*)array + pos*elem_size,
+		    (char*)array + (pos+1)*elem_size,
+		    (count-pos-1)*elem_size);
+    }
+}
+
+PJ_DEF(pj_status_t) pj_array_find( const void *array, 
+				   unsigned elem_size, 
+				   unsigned count, 
+				   pj_status_t (*matching)(const void *value),
+				   void **result)
+{
+    unsigned i;
+    const char *char_array = array;
+    for (i=0; i<count; ++i) {
+	if ( (*matching)(char_array) == PJ_SUCCESS) {
+	    if (result) {
+		*result = (void*)char_array;
+	    }
+	    return PJ_SUCCESS;
+	}
+	char_array += elem_size;
+    }
+    return PJ_ENOTFOUND;
+}
+
diff --git a/pjlib/src/pj/compat/sigjmp.c b/pjlib/src/pj/compat/sigjmp.c
index 9016176..6b07154 100644
--- a/pjlib/src/pj/compat/sigjmp.c
+++ b/pjlib/src/pj/compat/sigjmp.c
@@ -1,39 +1,39 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/config.h>

-#include <pj/compat/setjmp.h>

-

-int __sigjmp_save(sigjmp_buf env, int savemask)

-{

-    return 0;

-}

-

-extern int __sigsetjmp(pj_jmp_buf env, int savemask);

-extern void __longjmp(pj_jmp_buf env, int val) __attribute__((noreturn));

-

-PJ_DEF(int) pj_setjmp(pj_jmp_buf env)

-{

-    return __sigsetjmp(env, 0);

-}

-

-PJ_DEF(void) pj_longjmp(pj_jmp_buf env, int val)

-{

-    __longjmp(env, val);

-}

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/config.h>
+#include <pj/compat/setjmp.h>
+
+int __sigjmp_save(sigjmp_buf env, int savemask)
+{
+    return 0;
+}
+
+extern int __sigsetjmp(pj_jmp_buf env, int savemask);
+extern void __longjmp(pj_jmp_buf env, int val) __attribute__((noreturn));
+
+PJ_DEF(int) pj_setjmp(pj_jmp_buf env)
+{
+    return __sigsetjmp(env, 0);
+}
+
+PJ_DEF(void) pj_longjmp(pj_jmp_buf env, int val)
+{
+    __longjmp(env, val);
+}
+
diff --git a/pjlib/src/pj/compat/string.c b/pjlib/src/pj/compat/string.c
index 77fb1a5..bb2362c 100644
--- a/pjlib/src/pj/compat/string.c
+++ b/pjlib/src/pj/compat/string.c
@@ -1,44 +1,44 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/types.h>

-#include <pj/compat/string.h>

-#include <pj/ctype.h>

-

-PJ_DEF(int) strcasecmp(const char *s1, const char *s2)

-{

-    while ((*s1==*s2) || (pj_tolower(*s1)==pj_tolower(*s2))) {

-	if (!*s1++)

-	    return 0;

-	++s2;

-    }

-    return (pj_tolower(*s1) < pj_tolower(*s2)) ? -1 : 1;

-}

-

-PJ_DEF(int) strncasecmp(const char *s1, const char *s2, int len)

-{

-    if (!len) return 0;

-

-    while ((*s1==*s2) || (pj_tolower(*s1)==pj_tolower(*s2))) {

-	if (!*s1++ || --len <= 0)

-	    return 0;

-	++s2;

-    }

-    return (pj_tolower(*s1) < pj_tolower(*s2)) ? -1 : 1;

-}

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/types.h>
+#include <pj/compat/string.h>
+#include <pj/ctype.h>
+
+PJ_DEF(int) strcasecmp(const char *s1, const char *s2)
+{
+    while ((*s1==*s2) || (pj_tolower(*s1)==pj_tolower(*s2))) {
+	if (!*s1++)
+	    return 0;
+	++s2;
+    }
+    return (pj_tolower(*s1) < pj_tolower(*s2)) ? -1 : 1;
+}
+
+PJ_DEF(int) strncasecmp(const char *s1, const char *s2, int len)
+{
+    if (!len) return 0;
+
+    while ((*s1==*s2) || (pj_tolower(*s1)==pj_tolower(*s2))) {
+	if (!*s1++ || --len <= 0)
+	    return 0;
+	++s2;
+    }
+    return (pj_tolower(*s1) < pj_tolower(*s2)) ? -1 : 1;
+}
+
diff --git a/pjlib/src/pjlib++-test/main.cpp b/pjlib/src/pjlib++-test/main.cpp
index 86858a1..dc3b17e 100644
--- a/pjlib/src/pjlib++-test/main.cpp
+++ b/pjlib/src/pjlib++-test/main.cpp
@@ -1,61 +1,61 @@
-/* $Id */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj++/file.hpp>

-#include <pj++/list.hpp>

-#include <pj++/lock.hpp>

-#include <pj++/hash.hpp>

-#include <pj++/os.hpp>

-#include <pj++/proactor.hpp>

-#include <pj++/sock.hpp>

-#include <pj++/string.hpp>

-#include <pj++/timer.hpp>

-#include <pj++/tree.hpp>

-

-class My_Async_Op : public Pj_Async_Op

-{

-};

-

-class My_Event_Handler : public Pj_Event_Handler

-{

-};

-

-int main()

-{

-    Pjlib lib;

-    Pj_Caching_Pool mem;

-    Pj_Pool the_pool;

-    Pj_Pool *pool = &the_pool;

-    

-    the_pool.attach(mem.create_pool(4000,4000));

-

-    Pj_Semaphore_Lock lsem(pool);

-    Pj_Semaphore_Lock *plsem;

-

-    plsem = new(pool) Pj_Semaphore_Lock(pool);

-    delete plsem;

-

-    Pj_Proactor proactor(pool, 100, 100);

-

-    My_Event_Handler *event_handler = new(the_pool) My_Event_Handler;

-    proactor.register_socket_handler(pool, event_handler);

-    proactor.unregister_handler(event_handler);

-

-    return 0;

-}

-

+/* $Id */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj++/file.hpp>
+#include <pj++/list.hpp>
+#include <pj++/lock.hpp>
+#include <pj++/hash.hpp>
+#include <pj++/os.hpp>
+#include <pj++/proactor.hpp>
+#include <pj++/sock.hpp>
+#include <pj++/string.hpp>
+#include <pj++/timer.hpp>
+#include <pj++/tree.hpp>
+
+class My_Async_Op : public Pj_Async_Op
+{
+};
+
+class My_Event_Handler : public Pj_Event_Handler
+{
+};
+
+int main()
+{
+    Pjlib lib;
+    Pj_Caching_Pool mem;
+    Pj_Pool the_pool;
+    Pj_Pool *pool = &the_pool;
+    
+    the_pool.attach(mem.create_pool(4000,4000));
+
+    Pj_Semaphore_Lock lsem(pool);
+    Pj_Semaphore_Lock *plsem;
+
+    plsem = new(pool) Pj_Semaphore_Lock(pool);
+    delete plsem;
+
+    Pj_Proactor proactor(pool, 100, 100);
+
+    My_Event_Handler *event_handler = new(the_pool) My_Event_Handler;
+    proactor.register_socket_handler(pool, event_handler);
+    proactor.unregister_handler(event_handler);
+
+    return 0;
+}
+
diff --git a/pjlib/src/pjlib-samples/except.c b/pjlib/src/pjlib-samples/except.c
index 6611a9d..3bbfa54 100644
--- a/pjlib/src/pjlib-samples/except.c
+++ b/pjlib/src/pjlib-samples/except.c
@@ -1,85 +1,85 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/except.h>

-#include <pj/rand.h>

-#include <stdio.h>

-#include <stdlib.h>

-

-/**

- * \page page_pjlib_samples_except_c Example: Exception Handling

- *

- * Below is sample program to demonstrate how to use exception handling.

- *

- * \includelineno pjlib-samples/except.c

- */

-

-static pj_exception_id_t NO_MEMORY, OTHER_EXCEPTION;

-

-static void randomly_throw_exception()

-{

-    if (pj_rand() % 2)

-        PJ_THROW(OTHER_EXCEPTION);

-}

-

-static void *my_malloc(size_t size)

-{

-    void *ptr = malloc(size);

-    if (!ptr)

-        PJ_THROW(NO_MEMORY);

-    return ptr;

-}

-

-static int test_exception()

-{

-    PJ_USE_EXCEPTION;

-    

-    PJ_TRY {

-        void *data = my_malloc(200);

-        free(data);

-        randomly_throw_exception();

-    }

-    PJ_CATCH( NO_MEMORY ) {

-        puts("Can't allocate memory");

-        return 0;

-    }

-    PJ_DEFAULT {

-        pj_exception_id_t x_id;

-        

-        x_id = PJ_GET_EXCEPTION();

-        printf("Caught exception %d (%s)\n", 

-            x_id, pj_exception_id_name(x_id));

-    }

-    PJ_END

-        return 1;

-}

-

-int main()

-{

-    pj_status_t rc;

-    

-    // Error handling is omited for clarity.

-    

-    rc = pj_init();

-

-    rc = pj_exception_id_alloc("No Memory", &NO_MEMORY);

-    rc = pj_exception_id_alloc("Other Exception", &OTHER_EXCEPTION);

-    

-    return test_exception();

-}

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/except.h>
+#include <pj/rand.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ * \page page_pjlib_samples_except_c Example: Exception Handling
+ *
+ * Below is sample program to demonstrate how to use exception handling.
+ *
+ * \includelineno pjlib-samples/except.c
+ */
+
+static pj_exception_id_t NO_MEMORY, OTHER_EXCEPTION;
+
+static void randomly_throw_exception()
+{
+    if (pj_rand() % 2)
+        PJ_THROW(OTHER_EXCEPTION);
+}
+
+static void *my_malloc(size_t size)
+{
+    void *ptr = malloc(size);
+    if (!ptr)
+        PJ_THROW(NO_MEMORY);
+    return ptr;
+}
+
+static int test_exception()
+{
+    PJ_USE_EXCEPTION;
+    
+    PJ_TRY {
+        void *data = my_malloc(200);
+        free(data);
+        randomly_throw_exception();
+    }
+    PJ_CATCH( NO_MEMORY ) {
+        puts("Can't allocate memory");
+        return 0;
+    }
+    PJ_DEFAULT {
+        pj_exception_id_t x_id;
+        
+        x_id = PJ_GET_EXCEPTION();
+        printf("Caught exception %d (%s)\n", 
+            x_id, pj_exception_id_name(x_id));
+    }
+    PJ_END
+        return 1;
+}
+
+int main()
+{
+    pj_status_t rc;
+    
+    // Error handling is omited for clarity.
+    
+    rc = pj_init();
+
+    rc = pj_exception_id_alloc("No Memory", &NO_MEMORY);
+    rc = pj_exception_id_alloc("Other Exception", &OTHER_EXCEPTION);
+    
+    return test_exception();
+}
+
diff --git a/pjlib/src/pjlib-samples/list.c b/pjlib/src/pjlib-samples/list.c
index 6f089da..72e514e 100644
--- a/pjlib/src/pjlib-samples/list.c
+++ b/pjlib/src/pjlib-samples/list.c
@@ -1,71 +1,71 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/list.h>

-#include <pj/assert.h>

-#include <pj/log.h>

-

-/**

- * \page page_pjlib_samples_list_c Example: List Manipulation

- *

- * Below is sample program to demonstrate how to manipulate linked list.

- *

- * \includelineno pjlib-samples/list.c

- */

-

-struct my_node

-{

-    // This must be the first member declared in the struct!

-    PJ_DECL_LIST_MEMBER(struct my_node);

-    int value;

-};

-

-

-int main()

-{

-    struct my_node nodes[10];

-    struct my_node list;

-    struct my_node *it;

-    int i;

-    

-    // Initialize the list as empty.

-    pj_list_init(&list);

-    

-    // Insert nodes.

-    for (i=0; i<10; ++i) {

-        nodes[i].value = i;

-        pj_list_insert_before(&list, &nodes[i]);

-    }

-    

-    // Iterate list nodes.

-    it = list.next;

-    while (it != &list) {

-        PJ_LOG(3,("list", "value = %d", it->value));

-        it = it->next;

-    }

-    

-    // Erase all nodes.

-    for (i=0; i<10; ++i) {

-        pj_list_erase(&nodes[i]);

-    }

-    

-    // List must be empty by now.

-    pj_assert( pj_list_empty(&list) );

-    

-    return 0;

-};

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/list.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+
+/**
+ * \page page_pjlib_samples_list_c Example: List Manipulation
+ *
+ * Below is sample program to demonstrate how to manipulate linked list.
+ *
+ * \includelineno pjlib-samples/list.c
+ */
+
+struct my_node
+{
+    // This must be the first member declared in the struct!
+    PJ_DECL_LIST_MEMBER(struct my_node);
+    int value;
+};
+
+
+int main()
+{
+    struct my_node nodes[10];
+    struct my_node list;
+    struct my_node *it;
+    int i;
+    
+    // Initialize the list as empty.
+    pj_list_init(&list);
+    
+    // Insert nodes.
+    for (i=0; i<10; ++i) {
+        nodes[i].value = i;
+        pj_list_insert_before(&list, &nodes[i]);
+    }
+    
+    // Iterate list nodes.
+    it = list.next;
+    while (it != &list) {
+        PJ_LOG(3,("list", "value = %d", it->value));
+        it = it->next;
+    }
+    
+    // Erase all nodes.
+    for (i=0; i<10; ++i) {
+        pj_list_erase(&nodes[i]);
+    }
+    
+    // List must be empty by now.
+    pj_assert( pj_list_empty(&list) );
+    
+    return 0;
+};
diff --git a/pjlib/src/pjlib-samples/log.c b/pjlib/src/pjlib-samples/log.c
index e671264..dffcb72 100644
--- a/pjlib/src/pjlib-samples/log.c
+++ b/pjlib/src/pjlib-samples/log.c
@@ -1,42 +1,42 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/log.h>

-

-/**

- * \page page_pjlib_samples_log_c Example: Log, Hello World

- *

- * Very simple program to write log.

- *

- * \includelineno pjlib-samples/log.c

- */

-

-int main()

-{

-    pj_status_t rc;

-

-    // Error handling omited for clarity

-    

-    // Must initialize PJLIB first!

-    rc = pj_init();

-

-    PJ_LOG(3, ("main.c", "Hello world!"));

-

-    return 0;

-}

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/log.h>
+
+/**
+ * \page page_pjlib_samples_log_c Example: Log, Hello World
+ *
+ * Very simple program to write log.
+ *
+ * \includelineno pjlib-samples/log.c
+ */
+
+int main()
+{
+    pj_status_t rc;
+
+    // Error handling omited for clarity
+    
+    // Must initialize PJLIB first!
+    rc = pj_init();
+
+    PJ_LOG(3, ("main.c", "Hello world!"));
+
+    return 0;
+}
+
diff --git a/pjlib/src/pjlib-test/atomic.c b/pjlib/src/pjlib-test/atomic.c
index 2f6acc5..a7fbe60 100644
--- a/pjlib/src/pjlib-test/atomic.c
+++ b/pjlib/src/pjlib-test/atomic.c
@@ -1,108 +1,108 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pjlib.h>

-

-/**

- * \page page_pjlib_atomic_test Test: Atomic Variable

- *

- * This file provides implementation of \b atomic_test(). It tests the

- * functionality of the atomic variable API.

- *

- * \section atomic_test_sec Scope of the Test

- *

- * API tested:

- *  - pj_atomic_create()

- *  - pj_atomic_get()

- *  - pj_atomic_inc()

- *  - pj_atomic_dec()

- *  - pj_atomic_set()

- *  - pj_atomic_destroy()

- *

- *

- * This file is <b>pjlib-test/atomic.c</b>

- *

- * \include pjlib-test/atomic.c

- */

-

-

-#if INCLUDE_ATOMIC_TEST

-

-int atomic_test(void)

-{

-    pj_pool_t *pool;

-    pj_atomic_t *atomic_var;

-    pj_status_t rc;

-

-    pool = pj_pool_create(mem, NULL, 4096, 0, NULL);

-    if (!pool)

-        return -10;

-

-    /* create() */

-    rc = pj_atomic_create(pool, 111, &atomic_var);

-    if (rc != 0) {

-        return -20;

-    }

-

-    /* get: check the value. */

-    if (pj_atomic_get(atomic_var) != 111)

-        return -30;

-

-    /* increment. */

-    pj_atomic_inc(atomic_var);

-    if (pj_atomic_get(atomic_var) != 112)

-        return -40;

-

-    /* decrement. */

-    pj_atomic_dec(atomic_var);

-    if (pj_atomic_get(atomic_var) != 111)

-        return -50;

-

-    /* set */

-    pj_atomic_set(atomic_var, 211);

-    if (pj_atomic_get(atomic_var) != 211)

-        return -60;

-

-    /* add */

-    pj_atomic_add(atomic_var, 10);

-    if (pj_atomic_get(atomic_var) != 221)

-        return -60;

-

-    /* check the value again. */

-    if (pj_atomic_get(atomic_var) != 221)

-        return -70;

-

-    /* destroy */

-    rc = pj_atomic_destroy(atomic_var);

-    if (rc != 0)

-        return -80;

-

-    pj_pool_release(pool);

-

-    return 0;

-}

-

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_atomic_test;

-#endif  /* INCLUDE_ATOMIC_TEST */

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib.h>
+
+/**
+ * \page page_pjlib_atomic_test Test: Atomic Variable
+ *
+ * This file provides implementation of \b atomic_test(). It tests the
+ * functionality of the atomic variable API.
+ *
+ * \section atomic_test_sec Scope of the Test
+ *
+ * API tested:
+ *  - pj_atomic_create()
+ *  - pj_atomic_get()
+ *  - pj_atomic_inc()
+ *  - pj_atomic_dec()
+ *  - pj_atomic_set()
+ *  - pj_atomic_destroy()
+ *
+ *
+ * This file is <b>pjlib-test/atomic.c</b>
+ *
+ * \include pjlib-test/atomic.c
+ */
+
+
+#if INCLUDE_ATOMIC_TEST
+
+int atomic_test(void)
+{
+    pj_pool_t *pool;
+    pj_atomic_t *atomic_var;
+    pj_status_t rc;
+
+    pool = pj_pool_create(mem, NULL, 4096, 0, NULL);
+    if (!pool)
+        return -10;
+
+    /* create() */
+    rc = pj_atomic_create(pool, 111, &atomic_var);
+    if (rc != 0) {
+        return -20;
+    }
+
+    /* get: check the value. */
+    if (pj_atomic_get(atomic_var) != 111)
+        return -30;
+
+    /* increment. */
+    pj_atomic_inc(atomic_var);
+    if (pj_atomic_get(atomic_var) != 112)
+        return -40;
+
+    /* decrement. */
+    pj_atomic_dec(atomic_var);
+    if (pj_atomic_get(atomic_var) != 111)
+        return -50;
+
+    /* set */
+    pj_atomic_set(atomic_var, 211);
+    if (pj_atomic_get(atomic_var) != 211)
+        return -60;
+
+    /* add */
+    pj_atomic_add(atomic_var, 10);
+    if (pj_atomic_get(atomic_var) != 221)
+        return -60;
+
+    /* check the value again. */
+    if (pj_atomic_get(atomic_var) != 221)
+        return -70;
+
+    /* destroy */
+    rc = pj_atomic_destroy(atomic_var);
+    if (rc != 0)
+        return -80;
+
+    pj_pool_release(pool);
+
+    return 0;
+}
+
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_atomic_test;
+#endif  /* INCLUDE_ATOMIC_TEST */
+
diff --git a/pjlib/src/pjlib-test/echo_clt.c b/pjlib/src/pjlib-test/echo_clt.c
index a9d8183..2453d12 100644
--- a/pjlib/src/pjlib-test/echo_clt.c
+++ b/pjlib/src/pjlib-test/echo_clt.c
@@ -1,268 +1,268 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pjlib.h>

-

-#if INCLUDE_ECHO_CLIENT

-

-enum { BUF_SIZE = 512 };

-

-struct client

-{

-    int sock_type;

-    const char *server;

-    int port;

-};

-

-static pj_atomic_t *totalBytes;

-static pj_atomic_t *timeout_counter;

-static pj_atomic_t *invalid_counter;

-

-#define MSEC_PRINT_DURATION 1000

-

-static int wait_socket(pj_sock_t sock, unsigned msec_timeout)

-{

-    pj_fd_set_t fdset;

-    pj_time_val timeout;

-

-    timeout.sec = 0;

-    timeout.msec = msec_timeout;

-    pj_time_val_normalize(&timeout);

-

-    PJ_FD_ZERO(&fdset);

-    PJ_FD_SET(sock, &fdset);

-    

-    return pj_sock_select(FD_SETSIZE, &fdset, NULL, NULL, &timeout);

-}

-

-static int echo_client_thread(void *arg)

-{

-    pj_sock_t sock;

-    char send_buf[BUF_SIZE];

-    char recv_buf[BUF_SIZE];

-    pj_sockaddr_in addr;

-    pj_str_t s;

-    pj_status_t rc;

-    pj_uint32_t buffer_id;

-    pj_uint32_t buffer_counter;

-    struct client *client = arg;

-    pj_status_t last_recv_err = PJ_SUCCESS, last_send_err = PJ_SUCCESS;

-    unsigned counter = 0;

-

-    rc = app_socket(PJ_AF_INET, client->sock_type, 0, -1, &sock);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...unable to create socket", rc);

-        return -10;

-    }

-

-    rc = pj_sockaddr_in_init( &addr, pj_cstr(&s, client->server), 

-                              (pj_uint16_t)client->port);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...unable to resolve server", rc);

-        return -15;

-    }

-

-    rc = pj_sock_connect(sock, &addr, sizeof(addr));

-    if (rc != PJ_SUCCESS) {

-        app_perror("...connect() error", rc);

-        pj_sock_close(sock);

-        return -20;

-    }

-

-    PJ_LOG(3,("", "...socket connected to %s:%d", 

-		  pj_inet_ntoa(addr.sin_addr),

-		  pj_ntohs(addr.sin_port)));

-

-    pj_memset(send_buf, 'A', BUF_SIZE);

-    send_buf[BUF_SIZE-1]='\0';

-

-    /* Give other thread chance to initialize themselves! */

-    pj_thread_sleep(200);

-

-    //PJ_LOG(3,("", "...thread %p running", pj_thread_this()));

-

-    buffer_id = (pj_uint32_t) pj_thread_this();

-    buffer_counter = 0;

-

-    *(pj_uint32_t*)send_buf = buffer_id;

-

-    for (;;) {

-        int rc;

-        pj_ssize_t bytes;

-

-	++counter;

-

-	//while (wait_socket(sock,0) > 0)

-	//    ;

-

-        /* Send a packet. */

-        bytes = BUF_SIZE;

-	*(pj_uint32_t*)(send_buf+4) = ++buffer_counter;

-        rc = pj_sock_send(sock, send_buf, &bytes, 0);

-        if (rc != PJ_SUCCESS || bytes != BUF_SIZE) {

-            if (rc != last_send_err) {

-                app_perror("...send() error", rc);

-                PJ_LOG(3,("", "...ignoring subsequent error.."));

-                last_send_err = rc;

-                pj_thread_sleep(100);

-            }

-            continue;

-        }

-

-        rc = wait_socket(sock, 500);

-        if (rc == 0) {

-            PJ_LOG(3,("", "...timeout"));

-	    bytes = 0;

-	    pj_atomic_inc(timeout_counter);

-	} else if (rc < 0) {

-	    rc = pj_get_netos_error();

-	    app_perror("...select() error", rc);

-	    break;

-        } else {

-            /* Receive back the original packet. */

-            bytes = 0;

-            do {

-                pj_ssize_t received = BUF_SIZE - bytes;

-                rc = pj_sock_recv(sock, recv_buf+bytes, &received, 0);

-                if (rc != PJ_SUCCESS || received == 0) {

-                    if (rc != last_recv_err) {

-                        app_perror("...recv() error", rc);

-                        PJ_LOG(3,("", "...ignoring subsequent error.."));

-                        last_recv_err = rc;

-                        pj_thread_sleep(100);

-                    }

-                    bytes = 0;

-		    received = 0;

-                    break;

-                }

-                bytes += received;

-            } while (bytes != BUF_SIZE && bytes != 0);

-        }

-

-        if (bytes == 0)

-            continue;

-

-        if (pj_memcmp(send_buf, recv_buf, BUF_SIZE) != 0) {

-	    recv_buf[BUF_SIZE-1] = '\0';

-            PJ_LOG(3,("", "...error: buffer %u has changed!\n"

-			  "send_buf=%s\n"

-			  "recv_buf=%s\n", 

-			  counter, send_buf, recv_buf));

-	    pj_atomic_inc(invalid_counter);

-        }

-

-        /* Accumulate total received. */

-	pj_atomic_add(totalBytes, bytes);

-    }

-

-    pj_sock_close(sock);

-    return 0;

-}

-

-int echo_client(int sock_type, const char *server, int port)

-{

-    pj_pool_t *pool;

-    pj_thread_t *thread[ECHO_CLIENT_MAX_THREADS];

-    pj_status_t rc;

-    struct client client;

-    int i;

-    pj_atomic_value_t last_received;

-    pj_timestamp last_report;

-

-    client.sock_type = sock_type;

-    client.server = server;

-    client.port = port;

-

-    pool = pj_pool_create( mem, NULL, 4000, 4000, NULL );

-

-    rc = pj_atomic_create(pool, 0, &totalBytes);

-    if (rc != PJ_SUCCESS) {

-        PJ_LOG(3,("", "...error: unable to create atomic variable", rc));

-        return -30;

-    }

-    rc = pj_atomic_create(pool, 0, &invalid_counter);

-    rc = pj_atomic_create(pool, 0, &timeout_counter);

-

-    PJ_LOG(3,("", "Echo client started"));

-    PJ_LOG(3,("", "  Destination: %s:%d", 

-                  ECHO_SERVER_ADDRESS, ECHO_SERVER_START_PORT));

-    PJ_LOG(3,("", "  Press Ctrl-C to exit"));

-

-    for (i=0; i<ECHO_CLIENT_MAX_THREADS; ++i) {

-        rc = pj_thread_create( pool, NULL, &echo_client_thread, &client, 

-                               PJ_THREAD_DEFAULT_STACK_SIZE, 0,

-                               &thread[i]);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error: unable to create thread", rc);

-            return -10;

-        }

-    }

-

-    last_received = 0;

-    pj_get_timestamp(&last_report);

-

-    for (;;) {

-	pj_timestamp now;

-	unsigned long received, cur_received;

-	unsigned msec;

-	pj_highprec_t bw;

-	pj_time_val elapsed;

-	unsigned bw32;

-	pj_uint32_t timeout, invalid;

-

-	pj_thread_sleep(1000);

-

-	pj_get_timestamp(&now);

-	elapsed = pj_elapsed_time(&last_report, &now);

-	msec = PJ_TIME_VAL_MSEC(elapsed);

-

-	received = pj_atomic_get(totalBytes);

-	cur_received = received - last_received;

-	

-	bw = cur_received;

-	pj_highprec_mul(bw, 1000);

-	pj_highprec_div(bw, msec);

-

-	bw32 = (unsigned)bw;

-	

-	last_report = now;

-	last_received = received;

-

-	timeout = pj_atomic_get(timeout_counter);

-	invalid = pj_atomic_get(invalid_counter);

-

-        PJ_LOG(3,("", 

-	          "...%d threads, total bandwidth: %d KB/s, "

-		  "timeout=%d, invalid=%d", 

-                  ECHO_CLIENT_MAX_THREADS, bw32/1000,

-		  timeout, invalid));

-    }

-

-    for (i=0; i<ECHO_CLIENT_MAX_THREADS; ++i) {

-        pj_thread_join( thread[i] );

-    }

-

-    pj_pool_release(pool);

-    return 0;

-}

-

-

-#else

-int dummy_echo_client;

-#endif  /* INCLUDE_ECHO_CLIENT */

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib.h>
+
+#if INCLUDE_ECHO_CLIENT
+
+enum { BUF_SIZE = 512 };
+
+struct client
+{
+    int sock_type;
+    const char *server;
+    int port;
+};
+
+static pj_atomic_t *totalBytes;
+static pj_atomic_t *timeout_counter;
+static pj_atomic_t *invalid_counter;
+
+#define MSEC_PRINT_DURATION 1000
+
+static int wait_socket(pj_sock_t sock, unsigned msec_timeout)
+{
+    pj_fd_set_t fdset;
+    pj_time_val timeout;
+
+    timeout.sec = 0;
+    timeout.msec = msec_timeout;
+    pj_time_val_normalize(&timeout);
+
+    PJ_FD_ZERO(&fdset);
+    PJ_FD_SET(sock, &fdset);
+    
+    return pj_sock_select(FD_SETSIZE, &fdset, NULL, NULL, &timeout);
+}
+
+static int echo_client_thread(void *arg)
+{
+    pj_sock_t sock;
+    char send_buf[BUF_SIZE];
+    char recv_buf[BUF_SIZE];
+    pj_sockaddr_in addr;
+    pj_str_t s;
+    pj_status_t rc;
+    pj_uint32_t buffer_id;
+    pj_uint32_t buffer_counter;
+    struct client *client = arg;
+    pj_status_t last_recv_err = PJ_SUCCESS, last_send_err = PJ_SUCCESS;
+    unsigned counter = 0;
+
+    rc = app_socket(PJ_AF_INET, client->sock_type, 0, -1, &sock);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...unable to create socket", rc);
+        return -10;
+    }
+
+    rc = pj_sockaddr_in_init( &addr, pj_cstr(&s, client->server), 
+                              (pj_uint16_t)client->port);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...unable to resolve server", rc);
+        return -15;
+    }
+
+    rc = pj_sock_connect(sock, &addr, sizeof(addr));
+    if (rc != PJ_SUCCESS) {
+        app_perror("...connect() error", rc);
+        pj_sock_close(sock);
+        return -20;
+    }
+
+    PJ_LOG(3,("", "...socket connected to %s:%d", 
+		  pj_inet_ntoa(addr.sin_addr),
+		  pj_ntohs(addr.sin_port)));
+
+    pj_memset(send_buf, 'A', BUF_SIZE);
+    send_buf[BUF_SIZE-1]='\0';
+
+    /* Give other thread chance to initialize themselves! */
+    pj_thread_sleep(200);
+
+    //PJ_LOG(3,("", "...thread %p running", pj_thread_this()));
+
+    buffer_id = (pj_uint32_t) pj_thread_this();
+    buffer_counter = 0;
+
+    *(pj_uint32_t*)send_buf = buffer_id;
+
+    for (;;) {
+        int rc;
+        pj_ssize_t bytes;
+
+	++counter;
+
+	//while (wait_socket(sock,0) > 0)
+	//    ;
+
+        /* Send a packet. */
+        bytes = BUF_SIZE;
+	*(pj_uint32_t*)(send_buf+4) = ++buffer_counter;
+        rc = pj_sock_send(sock, send_buf, &bytes, 0);
+        if (rc != PJ_SUCCESS || bytes != BUF_SIZE) {
+            if (rc != last_send_err) {
+                app_perror("...send() error", rc);
+                PJ_LOG(3,("", "...ignoring subsequent error.."));
+                last_send_err = rc;
+                pj_thread_sleep(100);
+            }
+            continue;
+        }
+
+        rc = wait_socket(sock, 500);
+        if (rc == 0) {
+            PJ_LOG(3,("", "...timeout"));
+	    bytes = 0;
+	    pj_atomic_inc(timeout_counter);
+	} else if (rc < 0) {
+	    rc = pj_get_netos_error();
+	    app_perror("...select() error", rc);
+	    break;
+        } else {
+            /* Receive back the original packet. */
+            bytes = 0;
+            do {
+                pj_ssize_t received = BUF_SIZE - bytes;
+                rc = pj_sock_recv(sock, recv_buf+bytes, &received, 0);
+                if (rc != PJ_SUCCESS || received == 0) {
+                    if (rc != last_recv_err) {
+                        app_perror("...recv() error", rc);
+                        PJ_LOG(3,("", "...ignoring subsequent error.."));
+                        last_recv_err = rc;
+                        pj_thread_sleep(100);
+                    }
+                    bytes = 0;
+		    received = 0;
+                    break;
+                }
+                bytes += received;
+            } while (bytes != BUF_SIZE && bytes != 0);
+        }
+
+        if (bytes == 0)
+            continue;
+
+        if (pj_memcmp(send_buf, recv_buf, BUF_SIZE) != 0) {
+	    recv_buf[BUF_SIZE-1] = '\0';
+            PJ_LOG(3,("", "...error: buffer %u has changed!\n"
+			  "send_buf=%s\n"
+			  "recv_buf=%s\n", 
+			  counter, send_buf, recv_buf));
+	    pj_atomic_inc(invalid_counter);
+        }
+
+        /* Accumulate total received. */
+	pj_atomic_add(totalBytes, bytes);
+    }
+
+    pj_sock_close(sock);
+    return 0;
+}
+
+int echo_client(int sock_type, const char *server, int port)
+{
+    pj_pool_t *pool;
+    pj_thread_t *thread[ECHO_CLIENT_MAX_THREADS];
+    pj_status_t rc;
+    struct client client;
+    int i;
+    pj_atomic_value_t last_received;
+    pj_timestamp last_report;
+
+    client.sock_type = sock_type;
+    client.server = server;
+    client.port = port;
+
+    pool = pj_pool_create( mem, NULL, 4000, 4000, NULL );
+
+    rc = pj_atomic_create(pool, 0, &totalBytes);
+    if (rc != PJ_SUCCESS) {
+        PJ_LOG(3,("", "...error: unable to create atomic variable", rc));
+        return -30;
+    }
+    rc = pj_atomic_create(pool, 0, &invalid_counter);
+    rc = pj_atomic_create(pool, 0, &timeout_counter);
+
+    PJ_LOG(3,("", "Echo client started"));
+    PJ_LOG(3,("", "  Destination: %s:%d", 
+                  ECHO_SERVER_ADDRESS, ECHO_SERVER_START_PORT));
+    PJ_LOG(3,("", "  Press Ctrl-C to exit"));
+
+    for (i=0; i<ECHO_CLIENT_MAX_THREADS; ++i) {
+        rc = pj_thread_create( pool, NULL, &echo_client_thread, &client, 
+                               PJ_THREAD_DEFAULT_STACK_SIZE, 0,
+                               &thread[i]);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error: unable to create thread", rc);
+            return -10;
+        }
+    }
+
+    last_received = 0;
+    pj_get_timestamp(&last_report);
+
+    for (;;) {
+	pj_timestamp now;
+	unsigned long received, cur_received;
+	unsigned msec;
+	pj_highprec_t bw;
+	pj_time_val elapsed;
+	unsigned bw32;
+	pj_uint32_t timeout, invalid;
+
+	pj_thread_sleep(1000);
+
+	pj_get_timestamp(&now);
+	elapsed = pj_elapsed_time(&last_report, &now);
+	msec = PJ_TIME_VAL_MSEC(elapsed);
+
+	received = pj_atomic_get(totalBytes);
+	cur_received = received - last_received;
+	
+	bw = cur_received;
+	pj_highprec_mul(bw, 1000);
+	pj_highprec_div(bw, msec);
+
+	bw32 = (unsigned)bw;
+	
+	last_report = now;
+	last_received = received;
+
+	timeout = pj_atomic_get(timeout_counter);
+	invalid = pj_atomic_get(invalid_counter);
+
+        PJ_LOG(3,("", 
+	          "...%d threads, total bandwidth: %d KB/s, "
+		  "timeout=%d, invalid=%d", 
+                  ECHO_CLIENT_MAX_THREADS, bw32/1000,
+		  timeout, invalid));
+    }
+
+    for (i=0; i<ECHO_CLIENT_MAX_THREADS; ++i) {
+        pj_thread_join( thread[i] );
+    }
+
+    pj_pool_release(pool);
+    return 0;
+}
+
+
+#else
+int dummy_echo_client;
+#endif  /* INCLUDE_ECHO_CLIENT */
diff --git a/pjlib/src/pjlib-test/errno.c b/pjlib/src/pjlib-test/errno.c
index 1a2560c..999f352 100644
--- a/pjlib/src/pjlib-test/errno.c
+++ b/pjlib/src/pjlib-test/errno.c
@@ -1,162 +1,162 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pj/errno.h>

-#include <pj/log.h>

-#include <pj/ctype.h>

-#include <pj/compat/socket.h>

-#include <pj/string.h>

-

-#if INCLUDE_ERRNO_TEST

-

-#define THIS_FILE   "errno"

-

-#if defined(PJ_WIN32) && PJ_WIN32 != 0

-#   include <windows.h>

-#endif

-

-#if defined(PJ_HAS_ERRNO_H) && PJ_HAS_ERRNO_H != 0

-#   include <errno.h>

-#endif

-

-static void trim_newlines(char *s)

-{

-    while (*s) {

-        if (*s == '\r' || *s == '\n')

-            *s = ' ';

-        ++s;

-    }

-}

-

-int my_strncasecmp(const char *s1, const char *s2, int max_len)

-{

-    while (*s1 && *s2 && max_len > 0) {

-        if (pj_tolower(*s1) != pj_tolower(*s2))

-            return -1;

-        ++s1;

-        ++s2;

-        --max_len;

-    }

-    return 0;

-}

-

-const char *my_stristr(const char *whole, const char *part)

-{

-    int part_len = strlen(part);

-    while (*whole) {

-        if (my_strncasecmp(whole, part, part_len) == 0)

-            return whole;

-        ++whole;

-    }

-    return NULL;

-}

-

-int errno_test(void)

-{

-    enum { CUT = 6 };

-    pj_status_t rc;

-    char errbuf[256];

-

-    PJ_LOG(3,(THIS_FILE, "...errno test: check the msg carefully"));

-

-    /* 

-     * Windows platform error. 

-     */

-#   ifdef ERROR_INVALID_DATA

-    rc = PJ_STATUS_FROM_OS(ERROR_INVALID_DATA);

-    pj_set_os_error(rc);

-

-    /* Whole */

-    pj_strerror(rc, errbuf, sizeof(errbuf));

-    trim_newlines(errbuf);

-    PJ_LOG(3,(THIS_FILE, "...msg for rc=ERROR_INVALID_DATA: '%s'", errbuf));

-    if (my_stristr(errbuf, "invalid") == NULL) {

-        PJ_LOG(3, (THIS_FILE, 

-                   "...error: expecting \"invalid\" string in the msg"));

-        return -20;

-    }

-

-    /* Cut version. */

-    pj_strerror(rc, errbuf, CUT);

-    PJ_LOG(3,(THIS_FILE, "...msg for rc=ERROR_INVALID_DATA (cut): '%s'", errbuf));

-#   endif

-

-    /*

-     * Unix errors

-     */

-#   ifdef EINVAL

-    rc = PJ_STATUS_FROM_OS(EINVAL);

-    pj_set_os_error(rc);

-

-    /* Whole */

-    pj_strerror(rc, errbuf, sizeof(errbuf));

-    trim_newlines(errbuf);

-    PJ_LOG(3,(THIS_FILE, "...msg for rc=EINVAL: '%s'", errbuf));

-    if (my_stristr(errbuf, "invalid") == NULL) {

-        PJ_LOG(3, (THIS_FILE, 

-                   "...error: expecting \"invalid\" string in the msg"));

-        return -30;

-    }

-

-    /* Cut */

-    pj_strerror(rc, errbuf, CUT);

-    PJ_LOG(3,(THIS_FILE, "...msg for rc=EINVAL (cut): '%s'", errbuf));

-#   endif

-

-    /* 

-     * Windows WSA errors

-     */

-#   ifdef WSAEINVAL

-    rc = PJ_STATUS_FROM_OS(WSAEINVAL);

-    pj_set_os_error(rc);

-

-    /* Whole */

-    pj_strerror(rc, errbuf, sizeof(errbuf));

-    trim_newlines(errbuf);

-    PJ_LOG(3,(THIS_FILE, "...msg for rc=WSAEINVAL: '%s'", errbuf));

-    if (my_stristr(errbuf, "invalid") == NULL) {

-        PJ_LOG(3, (THIS_FILE, 

-                   "...error: expecting \"invalid\" string in the msg"));

-        return -40;

-    }

-

-    /* Cut */

-    pj_strerror(rc, errbuf, CUT);

-    PJ_LOG(3,(THIS_FILE, "...msg for rc=WSAEINVAL (cut): '%s'", errbuf));

-#   endif

-

-    pj_strerror(PJ_EBUG, errbuf, sizeof(errbuf));

-    PJ_LOG(3,(THIS_FILE, "...msg for rc=PJ_EBUG: '%s'", errbuf));

-    if (my_stristr(errbuf, "BUG") == NULL) {

-        PJ_LOG(3, (THIS_FILE, 

-                   "...error: expecting \"BUG\" string in the msg"));

-        return -20;

-    }

-

-    pj_strerror(PJ_EBUG, errbuf, CUT);

-    PJ_LOG(3,(THIS_FILE, "...msg for rc=PJ_EBUG, cut at %d chars: '%s'", 

-              CUT, errbuf));

-

-    return 0;

-}

-

-

-#endif	/* INCLUDE_ERRNO_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pj/errno.h>
+#include <pj/log.h>
+#include <pj/ctype.h>
+#include <pj/compat/socket.h>
+#include <pj/string.h>
+
+#if INCLUDE_ERRNO_TEST
+
+#define THIS_FILE   "errno"
+
+#if defined(PJ_WIN32) && PJ_WIN32 != 0
+#   include <windows.h>
+#endif
+
+#if defined(PJ_HAS_ERRNO_H) && PJ_HAS_ERRNO_H != 0
+#   include <errno.h>
+#endif
+
+static void trim_newlines(char *s)
+{
+    while (*s) {
+        if (*s == '\r' || *s == '\n')
+            *s = ' ';
+        ++s;
+    }
+}
+
+int my_strncasecmp(const char *s1, const char *s2, int max_len)
+{
+    while (*s1 && *s2 && max_len > 0) {
+        if (pj_tolower(*s1) != pj_tolower(*s2))
+            return -1;
+        ++s1;
+        ++s2;
+        --max_len;
+    }
+    return 0;
+}
+
+const char *my_stristr(const char *whole, const char *part)
+{
+    int part_len = strlen(part);
+    while (*whole) {
+        if (my_strncasecmp(whole, part, part_len) == 0)
+            return whole;
+        ++whole;
+    }
+    return NULL;
+}
+
+int errno_test(void)
+{
+    enum { CUT = 6 };
+    pj_status_t rc;
+    char errbuf[256];
+
+    PJ_LOG(3,(THIS_FILE, "...errno test: check the msg carefully"));
+
+    /* 
+     * Windows platform error. 
+     */
+#   ifdef ERROR_INVALID_DATA
+    rc = PJ_STATUS_FROM_OS(ERROR_INVALID_DATA);
+    pj_set_os_error(rc);
+
+    /* Whole */
+    pj_strerror(rc, errbuf, sizeof(errbuf));
+    trim_newlines(errbuf);
+    PJ_LOG(3,(THIS_FILE, "...msg for rc=ERROR_INVALID_DATA: '%s'", errbuf));
+    if (my_stristr(errbuf, "invalid") == NULL) {
+        PJ_LOG(3, (THIS_FILE, 
+                   "...error: expecting \"invalid\" string in the msg"));
+        return -20;
+    }
+
+    /* Cut version. */
+    pj_strerror(rc, errbuf, CUT);
+    PJ_LOG(3,(THIS_FILE, "...msg for rc=ERROR_INVALID_DATA (cut): '%s'", errbuf));
+#   endif
+
+    /*
+     * Unix errors
+     */
+#   ifdef EINVAL
+    rc = PJ_STATUS_FROM_OS(EINVAL);
+    pj_set_os_error(rc);
+
+    /* Whole */
+    pj_strerror(rc, errbuf, sizeof(errbuf));
+    trim_newlines(errbuf);
+    PJ_LOG(3,(THIS_FILE, "...msg for rc=EINVAL: '%s'", errbuf));
+    if (my_stristr(errbuf, "invalid") == NULL) {
+        PJ_LOG(3, (THIS_FILE, 
+                   "...error: expecting \"invalid\" string in the msg"));
+        return -30;
+    }
+
+    /* Cut */
+    pj_strerror(rc, errbuf, CUT);
+    PJ_LOG(3,(THIS_FILE, "...msg for rc=EINVAL (cut): '%s'", errbuf));
+#   endif
+
+    /* 
+     * Windows WSA errors
+     */
+#   ifdef WSAEINVAL
+    rc = PJ_STATUS_FROM_OS(WSAEINVAL);
+    pj_set_os_error(rc);
+
+    /* Whole */
+    pj_strerror(rc, errbuf, sizeof(errbuf));
+    trim_newlines(errbuf);
+    PJ_LOG(3,(THIS_FILE, "...msg for rc=WSAEINVAL: '%s'", errbuf));
+    if (my_stristr(errbuf, "invalid") == NULL) {
+        PJ_LOG(3, (THIS_FILE, 
+                   "...error: expecting \"invalid\" string in the msg"));
+        return -40;
+    }
+
+    /* Cut */
+    pj_strerror(rc, errbuf, CUT);
+    PJ_LOG(3,(THIS_FILE, "...msg for rc=WSAEINVAL (cut): '%s'", errbuf));
+#   endif
+
+    pj_strerror(PJ_EBUG, errbuf, sizeof(errbuf));
+    PJ_LOG(3,(THIS_FILE, "...msg for rc=PJ_EBUG: '%s'", errbuf));
+    if (my_stristr(errbuf, "BUG") == NULL) {
+        PJ_LOG(3, (THIS_FILE, 
+                   "...error: expecting \"BUG\" string in the msg"));
+        return -20;
+    }
+
+    pj_strerror(PJ_EBUG, errbuf, CUT);
+    PJ_LOG(3,(THIS_FILE, "...msg for rc=PJ_EBUG, cut at %d chars: '%s'", 
+              CUT, errbuf));
+
+    return 0;
+}
+
+
+#endif	/* INCLUDE_ERRNO_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/exception.c b/pjlib/src/pjlib-test/exception.c
index b09ba11..ef4bf4a 100644
--- a/pjlib/src/pjlib-test/exception.c
+++ b/pjlib/src/pjlib-test/exception.c
@@ -1,177 +1,177 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-

-/**

- * \page page_pjlib_exception_test Test: Exception Handling

- *

- * This file provides implementation of \b exception_test(). It tests the

- * functionality of the exception handling API.

- *

- * @note This test use static ID not acquired through proper registration.

- * This is not recommended, since it may create ID collissions.

- *

- * \section exception_test_sec Scope of the Test

- *

- * Some scenarios tested:

- *  - no exception situation

- *  - basic TRY/CATCH

- *  - multiple exception handlers

- *  - default handlers

- *

- *

- * This file is <b>pjlib-test/exception.c</b>

- *

- * \include pjlib-test/exception.c

- */

-

-

-#if INCLUDE_EXCEPTION_TEST

-

-#include <pjlib.h>

-

-#define	ID_1	1

-#define ID_2	2

-

-static int throw_id_1(void)

-{

-    PJ_THROW( ID_1 );

-    return -1;

-}

-

-static int throw_id_2(void)

-{

-    PJ_THROW( ID_2 );

-    return -1;

-}

-

-

-static int test(void)

-{

-    PJ_USE_EXCEPTION;

-    int rc = 0;

-

-    /*

-     * No exception situation.

-     */

-    PJ_TRY {

-        rc = rc;

-    }

-    PJ_CATCH( ID_1 ) {

-        rc = -2;

-    }

-    PJ_DEFAULT {

-        rc = -3;

-    }

-    PJ_END;

-

-    if (rc != 0)

-	return rc;

-

-

-    /*

-     * Basic TRY/CATCH

-     */ 

-    PJ_TRY {

-	rc = throw_id_1();

-

-	// should not reach here.

-	rc = -10;

-    }

-    PJ_CATCH( ID_1 ) {

-	if (!rc) rc = 0;

-    }

-    PJ_DEFAULT {

-        int id = PJ_GET_EXCEPTION();

-        PJ_LOG(3,("", "...error: got unexpected exception %d (%s)", 

-                  id, pj_exception_id_name(id)));

-	if (!rc) rc = -20;

-    }

-    PJ_END;

-

-    if (rc != 0)

-	return rc;

-

-    /*

-     * Multiple exceptions handlers

-     */

-    PJ_TRY {

-	rc = throw_id_2();

-	// should not reach here.

-	rc = -25;

-    }

-    PJ_CATCH( ID_1 ) {

-	if (!rc) rc = -30;

-    }

-    PJ_CATCH( ID_2 ) {

-	if (!rc) rc = 0;

-    }

-    PJ_DEFAULT {

-	if (!rc) rc = -40;

-    }

-    PJ_END;

-

-    if (rc != 0)

-	return rc;

-

-    /*

-     * Test default handler.

-     */

-    PJ_TRY {

-	rc = throw_id_1();

-	// should not reach here

-	rc = -50;

-    }

-    PJ_CATCH( ID_2 ) {

-	if (!rc) rc = -60;

-    }

-    PJ_DEFAULT {

-	if (!rc) rc = 0;

-    }

-    PJ_END;

-

-    if (rc != 0)

-	return rc;

-

-    return 0;

-}

-

-int exception_test(void)

-{

-    int i, rc;

-    enum { LOOP = 10 };

-

-    for (i=0; i<LOOP; ++i) {

-	if ((rc=test()) != 0) {

-	    PJ_LOG(3,("", "...failed at i=%d (rc=%d)", i, rc));

-	    return rc;

-	}

-    }

-    return 0;

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_exception_test;

-#endif	/* INCLUDE_EXCEPTION_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+
+/**
+ * \page page_pjlib_exception_test Test: Exception Handling
+ *
+ * This file provides implementation of \b exception_test(). It tests the
+ * functionality of the exception handling API.
+ *
+ * @note This test use static ID not acquired through proper registration.
+ * This is not recommended, since it may create ID collissions.
+ *
+ * \section exception_test_sec Scope of the Test
+ *
+ * Some scenarios tested:
+ *  - no exception situation
+ *  - basic TRY/CATCH
+ *  - multiple exception handlers
+ *  - default handlers
+ *
+ *
+ * This file is <b>pjlib-test/exception.c</b>
+ *
+ * \include pjlib-test/exception.c
+ */
+
+
+#if INCLUDE_EXCEPTION_TEST
+
+#include <pjlib.h>
+
+#define	ID_1	1
+#define ID_2	2
+
+static int throw_id_1(void)
+{
+    PJ_THROW( ID_1 );
+    return -1;
+}
+
+static int throw_id_2(void)
+{
+    PJ_THROW( ID_2 );
+    return -1;
+}
+
+
+static int test(void)
+{
+    PJ_USE_EXCEPTION;
+    int rc = 0;
+
+    /*
+     * No exception situation.
+     */
+    PJ_TRY {
+        rc = rc;
+    }
+    PJ_CATCH( ID_1 ) {
+        rc = -2;
+    }
+    PJ_DEFAULT {
+        rc = -3;
+    }
+    PJ_END;
+
+    if (rc != 0)
+	return rc;
+
+
+    /*
+     * Basic TRY/CATCH
+     */ 
+    PJ_TRY {
+	rc = throw_id_1();
+
+	// should not reach here.
+	rc = -10;
+    }
+    PJ_CATCH( ID_1 ) {
+	if (!rc) rc = 0;
+    }
+    PJ_DEFAULT {
+        int id = PJ_GET_EXCEPTION();
+        PJ_LOG(3,("", "...error: got unexpected exception %d (%s)", 
+                  id, pj_exception_id_name(id)));
+	if (!rc) rc = -20;
+    }
+    PJ_END;
+
+    if (rc != 0)
+	return rc;
+
+    /*
+     * Multiple exceptions handlers
+     */
+    PJ_TRY {
+	rc = throw_id_2();
+	// should not reach here.
+	rc = -25;
+    }
+    PJ_CATCH( ID_1 ) {
+	if (!rc) rc = -30;
+    }
+    PJ_CATCH( ID_2 ) {
+	if (!rc) rc = 0;
+    }
+    PJ_DEFAULT {
+	if (!rc) rc = -40;
+    }
+    PJ_END;
+
+    if (rc != 0)
+	return rc;
+
+    /*
+     * Test default handler.
+     */
+    PJ_TRY {
+	rc = throw_id_1();
+	// should not reach here
+	rc = -50;
+    }
+    PJ_CATCH( ID_2 ) {
+	if (!rc) rc = -60;
+    }
+    PJ_DEFAULT {
+	if (!rc) rc = 0;
+    }
+    PJ_END;
+
+    if (rc != 0)
+	return rc;
+
+    return 0;
+}
+
+int exception_test(void)
+{
+    int i, rc;
+    enum { LOOP = 10 };
+
+    for (i=0; i<LOOP; ++i) {
+	if ((rc=test()) != 0) {
+	    PJ_LOG(3,("", "...failed at i=%d (rc=%d)", i, rc));
+	    return rc;
+	}
+    }
+    return 0;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_exception_test;
+#endif	/* INCLUDE_EXCEPTION_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/fifobuf.c b/pjlib/src/pjlib-test/fifobuf.c
index 03917de..753ae25 100644
--- a/pjlib/src/pjlib-test/fifobuf.c
+++ b/pjlib/src/pjlib-test/fifobuf.c
@@ -1,116 +1,116 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_fifobuf_test;

-

-#if INCLUDE_FIFOBUF_TEST

-

-#include <pjlib.h>

-

-int fifobuf_test()

-{

-    enum { SIZE = 1024, MAX_ENTRIES = 128, 

-	   MIN_SIZE = 4, MAX_SIZE = 64, 

-	   LOOP=10000 };

-    pj_pool_t *pool;

-    pj_fifobuf_t fifo;

-    unsigned available = SIZE;

-    void *entries[MAX_ENTRIES];

-    void *buffer;

-    int i;

-

-    pool = pj_pool_create(mem, NULL, SIZE+256, 0, NULL);

-    if (!pool)

-	return -10;

-

-    buffer = pj_pool_alloc(pool, SIZE);

-    if (!buffer)

-	return -20;

-

-    pj_fifobuf_init (&fifo, buffer, SIZE);

-    

-    // Test 1

-    for (i=0; i<LOOP*MAX_ENTRIES; ++i) {

-	int size;

-	int c, f;

-	c = i%2;

-	f = (i+1)%2;

-	do {

-	    size = MIN_SIZE+(pj_rand() % MAX_SIZE);

-	    entries[c] = pj_fifobuf_alloc (&fifo, size);

-	} while (entries[c] == 0);

-	if ( i!=0) {

-	    pj_fifobuf_free(&fifo, entries[f]);

-	}

-    }

-    if (entries[(i+1)%2])

-	pj_fifobuf_free(&fifo, entries[(i+1)%2]);

-

-    if (pj_fifobuf_max_size(&fifo) < SIZE-4) {

-	pj_assert(0);

-	return -1;

-    }

-

-    // Test 2

-    entries[0] = pj_fifobuf_alloc (&fifo, MIN_SIZE);

-    if (!entries[0]) return -1;

-    for (i=0; i<LOOP*MAX_ENTRIES; ++i) {

-	int size = MIN_SIZE+(pj_rand() % MAX_SIZE);

-	entries[1] = pj_fifobuf_alloc (&fifo, size);

-	if (entries[1])

-	    pj_fifobuf_unalloc(&fifo, entries[1]);

-    }

-    pj_fifobuf_unalloc(&fifo, entries[0]);

-    if (pj_fifobuf_max_size(&fifo) < SIZE-4) {

-	pj_assert(0);

-	return -2;

-    }

-

-    // Test 3

-    for (i=0; i<LOOP; ++i) {

-	int count, j;

-	for (count=0; available>=MIN_SIZE+4 && count < MAX_ENTRIES;) {

-	    int size = MIN_SIZE+(pj_rand() % MAX_SIZE);

-	    entries[count] = pj_fifobuf_alloc (&fifo, size);

-	    if (entries[count]) {

-		available -= (size+4);

-		++count;

-	    }

-	}

-	for (j=0; j<count; ++j) {

-	    pj_fifobuf_free (&fifo, entries[j]);

-	}

-	available = SIZE;

-    }

-

-    if (pj_fifobuf_max_size(&fifo) < SIZE-4) {

-	pj_assert(0);

-	return -3;

-    }

-    pj_pool_release(pool);

-    return 0;

-}

-

-#endif	/* INCLUDE_FIFOBUF_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_fifobuf_test;
+
+#if INCLUDE_FIFOBUF_TEST
+
+#include <pjlib.h>
+
+int fifobuf_test()
+{
+    enum { SIZE = 1024, MAX_ENTRIES = 128, 
+	   MIN_SIZE = 4, MAX_SIZE = 64, 
+	   LOOP=10000 };
+    pj_pool_t *pool;
+    pj_fifobuf_t fifo;
+    unsigned available = SIZE;
+    void *entries[MAX_ENTRIES];
+    void *buffer;
+    int i;
+
+    pool = pj_pool_create(mem, NULL, SIZE+256, 0, NULL);
+    if (!pool)
+	return -10;
+
+    buffer = pj_pool_alloc(pool, SIZE);
+    if (!buffer)
+	return -20;
+
+    pj_fifobuf_init (&fifo, buffer, SIZE);
+    
+    // Test 1
+    for (i=0; i<LOOP*MAX_ENTRIES; ++i) {
+	int size;
+	int c, f;
+	c = i%2;
+	f = (i+1)%2;
+	do {
+	    size = MIN_SIZE+(pj_rand() % MAX_SIZE);
+	    entries[c] = pj_fifobuf_alloc (&fifo, size);
+	} while (entries[c] == 0);
+	if ( i!=0) {
+	    pj_fifobuf_free(&fifo, entries[f]);
+	}
+    }
+    if (entries[(i+1)%2])
+	pj_fifobuf_free(&fifo, entries[(i+1)%2]);
+
+    if (pj_fifobuf_max_size(&fifo) < SIZE-4) {
+	pj_assert(0);
+	return -1;
+    }
+
+    // Test 2
+    entries[0] = pj_fifobuf_alloc (&fifo, MIN_SIZE);
+    if (!entries[0]) return -1;
+    for (i=0; i<LOOP*MAX_ENTRIES; ++i) {
+	int size = MIN_SIZE+(pj_rand() % MAX_SIZE);
+	entries[1] = pj_fifobuf_alloc (&fifo, size);
+	if (entries[1])
+	    pj_fifobuf_unalloc(&fifo, entries[1]);
+    }
+    pj_fifobuf_unalloc(&fifo, entries[0]);
+    if (pj_fifobuf_max_size(&fifo) < SIZE-4) {
+	pj_assert(0);
+	return -2;
+    }
+
+    // Test 3
+    for (i=0; i<LOOP; ++i) {
+	int count, j;
+	for (count=0; available>=MIN_SIZE+4 && count < MAX_ENTRIES;) {
+	    int size = MIN_SIZE+(pj_rand() % MAX_SIZE);
+	    entries[count] = pj_fifobuf_alloc (&fifo, size);
+	    if (entries[count]) {
+		available -= (size+4);
+		++count;
+	    }
+	}
+	for (j=0; j<count; ++j) {
+	    pj_fifobuf_free (&fifo, entries[j]);
+	}
+	available = SIZE;
+    }
+
+    if (pj_fifobuf_max_size(&fifo) < SIZE-4) {
+	pj_assert(0);
+	return -3;
+    }
+    pj_pool_release(pool);
+    return 0;
+}
+
+#endif	/* INCLUDE_FIFOBUF_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/file.c b/pjlib/src/pjlib-test/file.c
index ffa72ef..d22c395 100644
--- a/pjlib/src/pjlib-test/file.c
+++ b/pjlib/src/pjlib-test/file.c
@@ -1,212 +1,212 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pjlib.h>

-

-#if INCLUDE_FILE_TEST

-

-#define FILENAME                "testfil1.txt"

-#define NEWNAME                 "testfil2.txt"

-#define INCLUDE_FILE_TIME_TEST  0

-

-static char buffer[11] = {'H', 'e', 'l', 'l', 'o', ' ',

-		          'W', 'o', 'r', 'l', 'd' };

-

-int file_test(void)

-{

-    enum { FILE_MAX_AGE = 1000 };

-    pj_oshandle_t fd = 0;

-    pj_status_t status;

-    char readbuf[sizeof(buffer)+16];

-    pj_file_stat stat;

-    pj_time_val start_time;

-    pj_ssize_t size;

-    pj_off_t pos;

-

-    PJ_LOG(3,("", "..file io test.."));

-

-    /* Get time. */

-    pj_gettimeofday(&start_time);

-

-    /* Delete original file if exists. */

-    if (pj_file_exists(FILENAME))

-        pj_file_delete(FILENAME);

-

-    /*

-     * Write data to the file.

-     */

-    status = pj_file_open(NULL, FILENAME, PJ_O_WRONLY, &fd);

-    if (status != PJ_SUCCESS) {

-        app_perror("...file_open() error", status);

-        return -10;

-    }

-

-    size = sizeof(buffer);

-    status = pj_file_write(fd, buffer, &size);

-    if (status != PJ_SUCCESS) {

-        app_perror("...file_write() error", status);

-        pj_file_close(fd);

-        return -20;

-    }

-    if (size != sizeof(buffer))

-        return -25;

-

-    status = pj_file_close(fd);

-    if (status != PJ_SUCCESS) {

-        app_perror("...file_close() error", status);

-        return -30;

-    }

-

-    /* Check the file existance and size. */

-    if (!pj_file_exists(FILENAME))

-        return -40;

-

-    if (pj_file_size(FILENAME) != sizeof(buffer))

-        return -50;

-

-    /* Get file stat. */

-    status = pj_file_getstat(FILENAME, &stat);

-    if (status != PJ_SUCCESS)

-        return -60;

-

-    /* Check stat size. */

-    if (stat.size != sizeof(buffer))

-        return -70;

-

-    /* Check file creation time >= start_time. */

-    if (!PJ_TIME_VAL_GTE(stat.ctime, start_time))

-#if INCLUDE_FILE_TIME_TEST

-        return -80;

-    /* Check file creation time is not much later. */

-    PJ_TIME_VAL_SUB(stat.ctime, start_time);

-    if (stat.ctime.sec > FILE_MAX_AGE)

-        return -90;

-

-    /* Check file modification time >= start_time. */

-    if (!PJ_TIME_VAL_GTE(stat.mtime, start_time))

-        return -80;

-    /* Check file modification time is not much later. */

-    PJ_TIME_VAL_SUB(stat.mtime, start_time);

-    if (stat.mtime.sec > FILE_MAX_AGE)

-        return -90;

-

-    /* Check file access time >= start_time. */

-    if (!PJ_TIME_VAL_GTE(stat.atime, start_time))

-        return -80;

-    /* Check file access time is not much later. */

-    PJ_TIME_VAL_SUB(stat.atime, start_time);

-    if (stat.atime.sec > FILE_MAX_AGE)

-        return -90;

-#endif

-

-    /*

-     * Re-open the file and read data.

-     */

-    status = pj_file_open(NULL, FILENAME, PJ_O_RDONLY, &fd);

-    if (status != PJ_SUCCESS) {

-        app_perror("...file_open() error", status);

-        return -100;

-    }

-

-    size = 0;

-    while (size < sizeof(readbuf)) {

-        pj_ssize_t read;

-        read = 1;

-        status = pj_file_read(fd, &readbuf[size], &read);

-        if (status != PJ_SUCCESS) {

-	    PJ_LOG(3,("", "...error reading file after %d bytes (error follows)", 

-		      size));

-            app_perror("...error", status);

-            return -110;

-        }

-        if (read == 0) {

-            // EOF

-            break;

-        }

-        size += read;

-    }

-

-    if (size != sizeof(buffer))

-        return -120;

-

-    /*

-    if (!pj_file_eof(fd, PJ_O_RDONLY))

-        return -130;

-     */

-

-    if (pj_memcmp(readbuf, buffer, size) != 0)

-        return -140;

-

-    /* Seek test. */

-    status = pj_file_setpos(fd, 4, PJ_SEEK_SET);

-    if (status != PJ_SUCCESS) {

-        app_perror("...file_setpos() error", status);

-        return -141;

-    }

-

-    /* getpos test. */

-    status = pj_file_getpos(fd, &pos);

-    if (status != PJ_SUCCESS) {

-        app_perror("...file_getpos() error", status);

-        return -142;

-    }

-    if (pos != 4)

-        return -143;

-

-    status = pj_file_close(fd);

-    if (status != PJ_SUCCESS) {

-        app_perror("...file_close() error", status);

-        return -150;

-    }

-

-    /*

-     * Rename test.

-     */

-    status = pj_file_move(FILENAME, NEWNAME);

-    if (status != PJ_SUCCESS) {

-        app_perror("...file_move() error", status);

-        return -160;

-    }

-

-    if (pj_file_exists(FILENAME))

-        return -170;

-    if (!pj_file_exists(NEWNAME))

-        return -180;

-

-    if (pj_file_size(NEWNAME) != sizeof(buffer))

-        return -190;

-

-    /* Delete test. */

-    status = pj_file_delete(NEWNAME);

-    if (status != PJ_SUCCESS) {

-        app_perror("...file_delete() error", status);

-        return -200;

-    }

-

-    if (pj_file_exists(NEWNAME))

-        return -210;

-

-    PJ_LOG(3,("", "...success"));

-    return PJ_SUCCESS;

-}

-

-#else

-int dummy_file_test;

-#endif

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib.h>
+
+#if INCLUDE_FILE_TEST
+
+#define FILENAME                "testfil1.txt"
+#define NEWNAME                 "testfil2.txt"
+#define INCLUDE_FILE_TIME_TEST  0
+
+static char buffer[11] = {'H', 'e', 'l', 'l', 'o', ' ',
+		          'W', 'o', 'r', 'l', 'd' };
+
+int file_test(void)
+{
+    enum { FILE_MAX_AGE = 1000 };
+    pj_oshandle_t fd = 0;
+    pj_status_t status;
+    char readbuf[sizeof(buffer)+16];
+    pj_file_stat stat;
+    pj_time_val start_time;
+    pj_ssize_t size;
+    pj_off_t pos;
+
+    PJ_LOG(3,("", "..file io test.."));
+
+    /* Get time. */
+    pj_gettimeofday(&start_time);
+
+    /* Delete original file if exists. */
+    if (pj_file_exists(FILENAME))
+        pj_file_delete(FILENAME);
+
+    /*
+     * Write data to the file.
+     */
+    status = pj_file_open(NULL, FILENAME, PJ_O_WRONLY, &fd);
+    if (status != PJ_SUCCESS) {
+        app_perror("...file_open() error", status);
+        return -10;
+    }
+
+    size = sizeof(buffer);
+    status = pj_file_write(fd, buffer, &size);
+    if (status != PJ_SUCCESS) {
+        app_perror("...file_write() error", status);
+        pj_file_close(fd);
+        return -20;
+    }
+    if (size != sizeof(buffer))
+        return -25;
+
+    status = pj_file_close(fd);
+    if (status != PJ_SUCCESS) {
+        app_perror("...file_close() error", status);
+        return -30;
+    }
+
+    /* Check the file existance and size. */
+    if (!pj_file_exists(FILENAME))
+        return -40;
+
+    if (pj_file_size(FILENAME) != sizeof(buffer))
+        return -50;
+
+    /* Get file stat. */
+    status = pj_file_getstat(FILENAME, &stat);
+    if (status != PJ_SUCCESS)
+        return -60;
+
+    /* Check stat size. */
+    if (stat.size != sizeof(buffer))
+        return -70;
+
+    /* Check file creation time >= start_time. */
+    if (!PJ_TIME_VAL_GTE(stat.ctime, start_time))
+#if INCLUDE_FILE_TIME_TEST
+        return -80;
+    /* Check file creation time is not much later. */
+    PJ_TIME_VAL_SUB(stat.ctime, start_time);
+    if (stat.ctime.sec > FILE_MAX_AGE)
+        return -90;
+
+    /* Check file modification time >= start_time. */
+    if (!PJ_TIME_VAL_GTE(stat.mtime, start_time))
+        return -80;
+    /* Check file modification time is not much later. */
+    PJ_TIME_VAL_SUB(stat.mtime, start_time);
+    if (stat.mtime.sec > FILE_MAX_AGE)
+        return -90;
+
+    /* Check file access time >= start_time. */
+    if (!PJ_TIME_VAL_GTE(stat.atime, start_time))
+        return -80;
+    /* Check file access time is not much later. */
+    PJ_TIME_VAL_SUB(stat.atime, start_time);
+    if (stat.atime.sec > FILE_MAX_AGE)
+        return -90;
+#endif
+
+    /*
+     * Re-open the file and read data.
+     */
+    status = pj_file_open(NULL, FILENAME, PJ_O_RDONLY, &fd);
+    if (status != PJ_SUCCESS) {
+        app_perror("...file_open() error", status);
+        return -100;
+    }
+
+    size = 0;
+    while (size < sizeof(readbuf)) {
+        pj_ssize_t read;
+        read = 1;
+        status = pj_file_read(fd, &readbuf[size], &read);
+        if (status != PJ_SUCCESS) {
+	    PJ_LOG(3,("", "...error reading file after %d bytes (error follows)", 
+		      size));
+            app_perror("...error", status);
+            return -110;
+        }
+        if (read == 0) {
+            // EOF
+            break;
+        }
+        size += read;
+    }
+
+    if (size != sizeof(buffer))
+        return -120;
+
+    /*
+    if (!pj_file_eof(fd, PJ_O_RDONLY))
+        return -130;
+     */
+
+    if (pj_memcmp(readbuf, buffer, size) != 0)
+        return -140;
+
+    /* Seek test. */
+    status = pj_file_setpos(fd, 4, PJ_SEEK_SET);
+    if (status != PJ_SUCCESS) {
+        app_perror("...file_setpos() error", status);
+        return -141;
+    }
+
+    /* getpos test. */
+    status = pj_file_getpos(fd, &pos);
+    if (status != PJ_SUCCESS) {
+        app_perror("...file_getpos() error", status);
+        return -142;
+    }
+    if (pos != 4)
+        return -143;
+
+    status = pj_file_close(fd);
+    if (status != PJ_SUCCESS) {
+        app_perror("...file_close() error", status);
+        return -150;
+    }
+
+    /*
+     * Rename test.
+     */
+    status = pj_file_move(FILENAME, NEWNAME);
+    if (status != PJ_SUCCESS) {
+        app_perror("...file_move() error", status);
+        return -160;
+    }
+
+    if (pj_file_exists(FILENAME))
+        return -170;
+    if (!pj_file_exists(NEWNAME))
+        return -180;
+
+    if (pj_file_size(NEWNAME) != sizeof(buffer))
+        return -190;
+
+    /* Delete test. */
+    status = pj_file_delete(NEWNAME);
+    if (status != PJ_SUCCESS) {
+        app_perror("...file_delete() error", status);
+        return -200;
+    }
+
+    if (pj_file_exists(NEWNAME))
+        return -210;
+
+    PJ_LOG(3,("", "...success"));
+    return PJ_SUCCESS;
+}
+
+#else
+int dummy_file_test;
+#endif
+
diff --git a/pjlib/src/pjlib-test/ioq_perf.c b/pjlib/src/pjlib-test/ioq_perf.c
index b10decc..3a8de8e 100644
--- a/pjlib/src/pjlib-test/ioq_perf.c
+++ b/pjlib/src/pjlib-test/ioq_perf.c
@@ -1,502 +1,502 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pjlib.h>

-#include <pj/compat/high_precision.h>

-

-/**

- * \page page_pjlib_ioqueue_perf_test Test: I/O Queue Performance

- *

- * Test the performance of the I/O queue, using typical producer

- * consumer test. The test should examine the effect of using multiple

- * threads on the performance.

- *

- * This file is <b>pjlib-test/ioq_perf.c</b>

- *

- * \include pjlib-test/ioq_perf.c

- */

-

-#if INCLUDE_IOQUEUE_PERF_TEST

-

-#ifdef _MSC_VER

-#   pragma warning ( disable: 4204)     // non-constant aggregate initializer

-#endif

-

-#define THIS_FILE	"ioq_perf"

-//#define TRACE_(expr)	PJ_LOG(3,expr)

-#define TRACE_(expr)

-

-

-static pj_bool_t thread_quit_flag;

-static pj_status_t last_error;

-static unsigned last_error_counter;

-

-/* Descriptor for each producer/consumer pair. */

-typedef struct test_item

-{

-    pj_sock_t            server_fd, 

-                         client_fd;

-    pj_ioqueue_t        *ioqueue;

-    pj_ioqueue_key_t    *server_key,

-                        *client_key;

-    pj_ioqueue_op_key_t  recv_op,

-                         send_op;

-    int                  has_pending_send;

-    pj_size_t            buffer_size;

-    char                *outgoing_buffer;

-    char                *incoming_buffer;

-    pj_size_t            bytes_sent, 

-                         bytes_recv;

-} test_item;

-

-/* Callback when data has been read.

- * Increment item->bytes_recv and ready to read the next data.

- */

-static void on_read_complete(pj_ioqueue_key_t *key, 

-                             pj_ioqueue_op_key_t *op_key,

-                             pj_ssize_t bytes_read)

-{

-    test_item *item = pj_ioqueue_get_user_data(key);

-    pj_status_t rc;

-    int data_is_available = 1;

-

-    //TRACE_((THIS_FILE, "     read complete, bytes_read=%d", bytes_read));

-

-    do {

-        if (thread_quit_flag)

-            return;

-

-        if (bytes_read < 0) {

-            pj_status_t rc = -bytes_read;

-            char errmsg[128];

-

-	    if (rc != last_error) {

-	        //last_error = rc;

-	        pj_strerror(rc, errmsg, sizeof(errmsg));

-	        PJ_LOG(3,(THIS_FILE, "...error: read error, bytes_read=%d (%s)", 

-		          bytes_read, errmsg));

-	        PJ_LOG(3,(THIS_FILE, 

-		          ".....additional info: total read=%u, total sent=%u",

-		          item->bytes_recv, item->bytes_sent));

-	    } else {

-	        last_error_counter++;

-	    }

-            bytes_read = 0;

-

-        } else if (bytes_read == 0) {

-            PJ_LOG(3,(THIS_FILE, "...socket has closed!"));

-        }

-

-        item->bytes_recv += bytes_read;

-    

-        /* To assure that the test quits, even if main thread

-         * doesn't have time to run.

-         */

-        if (item->bytes_recv > item->buffer_size * 10000) 

-	    thread_quit_flag = 1;

-

-        bytes_read = item->buffer_size;

-        rc = pj_ioqueue_recv( key, op_key,

-                              item->incoming_buffer, &bytes_read, 0 );

-

-        if (rc == PJ_SUCCESS) {

-            data_is_available = 1;

-        } else if (rc == PJ_EPENDING) {

-            data_is_available = 0;

-        } else {

-            data_is_available = 0;

-	    if (rc != last_error) {

-	        last_error = rc;

-	        app_perror("...error: read error(1)", rc);

-	    } else {

-	        last_error_counter++;

-	    }

-        }

-

-        if (!item->has_pending_send) {

-            pj_ssize_t sent = item->buffer_size;

-            rc = pj_ioqueue_send(item->client_key, &item->send_op,

-                                 item->outgoing_buffer, &sent, 0);

-            if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {

-                app_perror("...error: write error", rc);

-            }

-

-            item->has_pending_send = (rc==PJ_EPENDING);

-        }

-

-    } while (data_is_available);

-}

-

-/* Callback when data has been written.

- * Increment item->bytes_sent and write the next data.

- */

-static void on_write_complete(pj_ioqueue_key_t *key, 

-                              pj_ioqueue_op_key_t *op_key,

-                              pj_ssize_t bytes_sent)

-{

-    test_item *item = pj_ioqueue_get_user_data(key);

-    

-    //TRACE_((THIS_FILE, "     write complete: sent = %d", bytes_sent));

-

-    if (thread_quit_flag)

-        return;

-

-    item->has_pending_send = 0;

-    item->bytes_sent += bytes_sent;

-

-    if (bytes_sent <= 0) {

-        PJ_LOG(3,(THIS_FILE, "...error: sending stopped. bytes_sent=%d", 

-                  bytes_sent));

-    } 

-    else {

-        pj_status_t rc;

-

-        bytes_sent = item->buffer_size;

-        rc = pj_ioqueue_send( item->client_key, op_key,

-                              item->outgoing_buffer, &bytes_sent, 0);

-        if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {

-            app_perror("...error: write error", rc);

-        }

-

-        item->has_pending_send = (rc==PJ_EPENDING);

-    }

-}

-

-/* The worker thread. */

-static int worker_thread(void *arg)

-{

-    pj_ioqueue_t *ioqueue = arg;

-    const pj_time_val timeout = {0, 100};

-    int rc;

-

-    while (!thread_quit_flag) {

-        rc = pj_ioqueue_poll(ioqueue, &timeout);

-	//TRACE_((THIS_FILE, "     thread: poll returned rc=%d", rc));

-        if (rc < 0) {

-            app_perror("...error in pj_ioqueue_poll()", pj_get_netos_error());

-            return -1;

-        }

-    }

-    return 0;

-}

-

-/* Calculate the bandwidth for the specific test configuration.

- * The test is simple:

- *  - create sockpair_cnt number of producer-consumer socket pair.

- *  - create thread_cnt number of worker threads.

- *  - each producer will send buffer_size bytes data as fast and

- *    as soon as it can.

- *  - each consumer will read buffer_size bytes of data as fast 

- *    as it could.

- *  - measure the total bytes received by all consumers during a

- *    period of time.

- */

-static int perform_test(int sock_type, const char *type_name,

-                        unsigned thread_cnt, unsigned sockpair_cnt,

-                        pj_size_t buffer_size, 

-                        pj_size_t *p_bandwidth)

-{

-    enum { MSEC_DURATION = 5000 };

-    pj_pool_t *pool;

-    test_item *items;

-    pj_thread_t **thread;

-    pj_ioqueue_t *ioqueue;

-    pj_status_t rc;

-    pj_ioqueue_callback ioqueue_callback;

-    pj_uint32_t total_elapsed_usec, total_received;

-    pj_highprec_t bandwidth;

-    pj_timestamp start, stop;

-    unsigned i;

-

-    TRACE_((THIS_FILE, "    starting test.."));

-

-    ioqueue_callback.on_read_complete = &on_read_complete;

-    ioqueue_callback.on_write_complete = &on_write_complete;

-

-    thread_quit_flag = 0;

-

-    pool = pj_pool_create(mem, NULL, 4096, 4096, NULL);

-    if (!pool)

-        return -10;

-

-    items = pj_pool_alloc(pool, sockpair_cnt*sizeof(test_item));

-    thread = pj_pool_alloc(pool, thread_cnt*sizeof(pj_thread_t*));

-

-    TRACE_((THIS_FILE, "     creating ioqueue.."));

-    rc = pj_ioqueue_create(pool, sockpair_cnt*2, &ioqueue);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error: unable to create ioqueue", rc);

-        return -15;

-    }

-

-    /* Initialize each producer-consumer pair. */

-    for (i=0; i<sockpair_cnt; ++i) {

-        pj_ssize_t bytes;

-

-        items[i].ioqueue = ioqueue;

-        items[i].buffer_size = buffer_size;

-        items[i].outgoing_buffer = pj_pool_alloc(pool, buffer_size);

-        items[i].incoming_buffer = pj_pool_alloc(pool, buffer_size);

-        items[i].bytes_recv = items[i].bytes_sent = 0;

-

-        /* randomize outgoing buffer. */

-        pj_create_random_string(items[i].outgoing_buffer, buffer_size);

-

-        /* Create socket pair. */

-	TRACE_((THIS_FILE, "      calling socketpair.."));

-        rc = app_socketpair(PJ_AF_INET, sock_type, 0, 

-                            &items[i].server_fd, &items[i].client_fd);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error: unable to create socket pair", rc);

-            return -20;

-        }

-

-        /* Register server socket to ioqueue. */

-	TRACE_((THIS_FILE, "      register(1).."));

-        rc = pj_ioqueue_register_sock(pool, ioqueue, 

-                                      items[i].server_fd,

-                                      &items[i], &ioqueue_callback,

-                                      &items[i].server_key);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error: registering server socket to ioqueue", rc);

-            return -60;

-        }

-

-        /* Register client socket to ioqueue. */

-	TRACE_((THIS_FILE, "      register(2).."));

-        rc = pj_ioqueue_register_sock(pool, ioqueue, 

-                                      items[i].client_fd,

-                                      &items[i],  &ioqueue_callback,

-                                      &items[i].client_key);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error: registering server socket to ioqueue", rc);

-            return -70;

-        }

-

-        /* Start reading. */

-	TRACE_((THIS_FILE, "      pj_ioqueue_recv.."));

-        bytes = items[i].buffer_size;

-        rc = pj_ioqueue_recv(items[i].server_key, &items[i].recv_op,

-                             items[i].incoming_buffer, &bytes,

-			     0);

-        if (rc != PJ_EPENDING) {

-            app_perror("...error: pj_ioqueue_recv", rc);

-            return -73;

-        }

-

-        /* Start writing. */

-	TRACE_((THIS_FILE, "      pj_ioqueue_write.."));

-        bytes = items[i].buffer_size;

-        rc = pj_ioqueue_send(items[i].client_key, &items[i].recv_op,

-                             items[i].outgoing_buffer, &bytes, 0);

-        if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {

-            app_perror("...error: pj_ioqueue_write", rc);

-            return -76;

-        }

-

-        items[i].has_pending_send = (rc==PJ_EPENDING);

-    }

-

-    /* Create the threads. */

-    for (i=0; i<thread_cnt; ++i) {

-        rc = pj_thread_create( pool, NULL, 

-                               &worker_thread, 

-                               ioqueue, 

-                               PJ_THREAD_DEFAULT_STACK_SIZE, 

-                               PJ_THREAD_SUSPENDED, &thread[i] );

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error: unable to create thread", rc);

-            return -80;

-        }

-    }

-

-    /* Mark start time. */

-    rc = pj_get_timestamp(&start);

-    if (rc != PJ_SUCCESS)

-        return -90;

-

-    /* Start the thread. */

-    TRACE_((THIS_FILE, "     resuming all threads.."));

-    for (i=0; i<thread_cnt; ++i) {

-        rc = pj_thread_resume(thread[i]);

-        if (rc != 0)

-            return -100;

-    }

-

-    /* Wait for MSEC_DURATION seconds. 

-     * This should be as simple as pj_thread_sleep(MSEC_DURATION) actually,

-     * but unfortunately it doesn't work when system doesn't employ

-     * timeslicing for threads.

-     */

-    TRACE_((THIS_FILE, "     wait for few seconds.."));

-    do {

-	pj_thread_sleep(1);

-

-	/* Mark end time. */

-	rc = pj_get_timestamp(&stop);

-

-	if (thread_quit_flag) {

-	    TRACE_((THIS_FILE, "      transfer limit reached.."));

-	    break;

-	}

-

-	if (pj_elapsed_usec(&start,&stop)<MSEC_DURATION * 1000) {

-	    TRACE_((THIS_FILE, "      time limit reached.."));

-	    break;

-	}

-

-    } while (1);

-

-    /* Terminate all threads. */

-    TRACE_((THIS_FILE, "     terminating all threads.."));

-    thread_quit_flag = 1;

-

-    for (i=0; i<thread_cnt; ++i) {

-	TRACE_((THIS_FILE, "      join thread %d..", i));

-        pj_thread_join(thread[i]);

-        pj_thread_destroy(thread[i]);

-    }

-

-    /* Close all sockets. */

-    TRACE_((THIS_FILE, "     closing all sockets.."));

-    for (i=0; i<sockpair_cnt; ++i) {

-        pj_ioqueue_unregister(items[i].server_key);

-        pj_ioqueue_unregister(items[i].client_key);

-        pj_sock_close(items[i].server_fd);

-        pj_sock_close(items[i].client_fd);

-    }

-

-    /* Destroy ioqueue. */

-    TRACE_((THIS_FILE, "     destroying ioqueue.."));

-    pj_ioqueue_destroy(ioqueue);

-

-    /* Calculate actual time in usec. */

-    total_elapsed_usec = pj_elapsed_usec(&start, &stop);

-

-    /* Calculate total bytes received. */

-    total_received = 0;

-    for (i=0; i<sockpair_cnt; ++i) {

-        total_received = items[i].bytes_recv;

-    }

-

-    /* bandwidth = total_received*1000/total_elapsed_usec */

-    bandwidth = total_received;

-    pj_highprec_mul(bandwidth, 1000);

-    pj_highprec_div(bandwidth, total_elapsed_usec);

-    

-    *p_bandwidth = (pj_uint32_t)bandwidth;

-

-    PJ_LOG(3,(THIS_FILE, "   %.4s    %d         %d        %3d us  %8d KB/s",

-              type_name, thread_cnt, sockpair_cnt,

-              -1 /*total_elapsed_usec/sockpair_cnt*/,

-              *p_bandwidth));

-

-    /* Done. */

-    pj_pool_release(pool);

-

-    TRACE_((THIS_FILE, "    done.."));

-    return 0;

-}

-

-/*

- * main test entry.

- */

-int ioqueue_perf_test(void)

-{

-    enum { BUF_SIZE = 512 };

-    int i, rc;

-    struct {

-        int         type;

-        const char *type_name;

-        int         thread_cnt;

-        int         sockpair_cnt;

-    } test_param[] = 

-    {

-        { PJ_SOCK_DGRAM, "udp", 1, 1},

-        { PJ_SOCK_DGRAM, "udp", 1, 2},

-        { PJ_SOCK_DGRAM, "udp", 1, 4},

-        { PJ_SOCK_DGRAM, "udp", 1, 8},

-        { PJ_SOCK_DGRAM, "udp", 2, 1},

-        { PJ_SOCK_DGRAM, "udp", 2, 2},

-        { PJ_SOCK_DGRAM, "udp", 2, 4},

-        { PJ_SOCK_DGRAM, "udp", 2, 8},

-        { PJ_SOCK_DGRAM, "udp", 4, 1},

-        { PJ_SOCK_DGRAM, "udp", 4, 2},

-        { PJ_SOCK_DGRAM, "udp", 4, 4},

-        { PJ_SOCK_DGRAM, "udp", 4, 8},

-        { PJ_SOCK_STREAM, "tcp", 1, 1},

-        { PJ_SOCK_STREAM, "tcp", 1, 2},

-        { PJ_SOCK_STREAM, "tcp", 1, 4},

-        { PJ_SOCK_STREAM, "tcp", 1, 8},

-        { PJ_SOCK_STREAM, "tcp", 2, 1},

-        { PJ_SOCK_STREAM, "tcp", 2, 2},

-        { PJ_SOCK_STREAM, "tcp", 2, 4},

-        { PJ_SOCK_STREAM, "tcp", 2, 8},

-        { PJ_SOCK_STREAM, "tcp", 4, 1},

-        { PJ_SOCK_STREAM, "tcp", 4, 2},

-        { PJ_SOCK_STREAM, "tcp", 4, 4},

-        { PJ_SOCK_STREAM, "tcp", 4, 8},

-    };

-    pj_size_t best_bandwidth;

-    int best_index = 0;

-

-    PJ_LOG(3,(THIS_FILE, "   Benchmarking %s ioqueue:", pj_ioqueue_name()));

-    PJ_LOG(3,(THIS_FILE, "   ==============================================="));

-    PJ_LOG(3,(THIS_FILE, "   Type  Threads  Skt.Pairs  Avg.Time    Bandwidth"));

-    PJ_LOG(3,(THIS_FILE, "   ==============================================="));

-

-    best_bandwidth = 0;

-    for (i=0; i<sizeof(test_param)/sizeof(test_param[0]); ++i) {

-        pj_size_t bandwidth;

-

-        rc = perform_test(test_param[i].type, 

-                          test_param[i].type_name,

-                          test_param[i].thread_cnt, 

-                          test_param[i].sockpair_cnt, 

-                          BUF_SIZE, 

-                          &bandwidth);

-        if (rc != 0)

-            return rc;

-

-        if (bandwidth > best_bandwidth)

-            best_bandwidth = bandwidth, best_index = i;

-

-        /* Give it a rest before next test. */

-        pj_thread_sleep(500);

-    }

-

-    PJ_LOG(3,(THIS_FILE, 

-              "   Best: Type=%s Threads=%d, Skt.Pairs=%d, Bandwidth=%u KB/s",

-              test_param[best_index].type_name,

-              test_param[best_index].thread_cnt,

-              test_param[best_index].sockpair_cnt,

-              best_bandwidth));

-    PJ_LOG(3,(THIS_FILE, "   (Note: packet size=%d, total errors=%u)", 

-			 BUF_SIZE, last_error_counter));

-    return 0;

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_uiq_perf_test;

-#endif  /* INCLUDE_IOQUEUE_PERF_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib.h>
+#include <pj/compat/high_precision.h>
+
+/**
+ * \page page_pjlib_ioqueue_perf_test Test: I/O Queue Performance
+ *
+ * Test the performance of the I/O queue, using typical producer
+ * consumer test. The test should examine the effect of using multiple
+ * threads on the performance.
+ *
+ * This file is <b>pjlib-test/ioq_perf.c</b>
+ *
+ * \include pjlib-test/ioq_perf.c
+ */
+
+#if INCLUDE_IOQUEUE_PERF_TEST
+
+#ifdef _MSC_VER
+#   pragma warning ( disable: 4204)     // non-constant aggregate initializer
+#endif
+
+#define THIS_FILE	"ioq_perf"
+//#define TRACE_(expr)	PJ_LOG(3,expr)
+#define TRACE_(expr)
+
+
+static pj_bool_t thread_quit_flag;
+static pj_status_t last_error;
+static unsigned last_error_counter;
+
+/* Descriptor for each producer/consumer pair. */
+typedef struct test_item
+{
+    pj_sock_t            server_fd, 
+                         client_fd;
+    pj_ioqueue_t        *ioqueue;
+    pj_ioqueue_key_t    *server_key,
+                        *client_key;
+    pj_ioqueue_op_key_t  recv_op,
+                         send_op;
+    int                  has_pending_send;
+    pj_size_t            buffer_size;
+    char                *outgoing_buffer;
+    char                *incoming_buffer;
+    pj_size_t            bytes_sent, 
+                         bytes_recv;
+} test_item;
+
+/* Callback when data has been read.
+ * Increment item->bytes_recv and ready to read the next data.
+ */
+static void on_read_complete(pj_ioqueue_key_t *key, 
+                             pj_ioqueue_op_key_t *op_key,
+                             pj_ssize_t bytes_read)
+{
+    test_item *item = pj_ioqueue_get_user_data(key);
+    pj_status_t rc;
+    int data_is_available = 1;
+
+    //TRACE_((THIS_FILE, "     read complete, bytes_read=%d", bytes_read));
+
+    do {
+        if (thread_quit_flag)
+            return;
+
+        if (bytes_read < 0) {
+            pj_status_t rc = -bytes_read;
+            char errmsg[128];
+
+	    if (rc != last_error) {
+	        //last_error = rc;
+	        pj_strerror(rc, errmsg, sizeof(errmsg));
+	        PJ_LOG(3,(THIS_FILE, "...error: read error, bytes_read=%d (%s)", 
+		          bytes_read, errmsg));
+	        PJ_LOG(3,(THIS_FILE, 
+		          ".....additional info: total read=%u, total sent=%u",
+		          item->bytes_recv, item->bytes_sent));
+	    } else {
+	        last_error_counter++;
+	    }
+            bytes_read = 0;
+
+        } else if (bytes_read == 0) {
+            PJ_LOG(3,(THIS_FILE, "...socket has closed!"));
+        }
+
+        item->bytes_recv += bytes_read;
+    
+        /* To assure that the test quits, even if main thread
+         * doesn't have time to run.
+         */
+        if (item->bytes_recv > item->buffer_size * 10000) 
+	    thread_quit_flag = 1;
+
+        bytes_read = item->buffer_size;
+        rc = pj_ioqueue_recv( key, op_key,
+                              item->incoming_buffer, &bytes_read, 0 );
+
+        if (rc == PJ_SUCCESS) {
+            data_is_available = 1;
+        } else if (rc == PJ_EPENDING) {
+            data_is_available = 0;
+        } else {
+            data_is_available = 0;
+	    if (rc != last_error) {
+	        last_error = rc;
+	        app_perror("...error: read error(1)", rc);
+	    } else {
+	        last_error_counter++;
+	    }
+        }
+
+        if (!item->has_pending_send) {
+            pj_ssize_t sent = item->buffer_size;
+            rc = pj_ioqueue_send(item->client_key, &item->send_op,
+                                 item->outgoing_buffer, &sent, 0);
+            if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
+                app_perror("...error: write error", rc);
+            }
+
+            item->has_pending_send = (rc==PJ_EPENDING);
+        }
+
+    } while (data_is_available);
+}
+
+/* Callback when data has been written.
+ * Increment item->bytes_sent and write the next data.
+ */
+static void on_write_complete(pj_ioqueue_key_t *key, 
+                              pj_ioqueue_op_key_t *op_key,
+                              pj_ssize_t bytes_sent)
+{
+    test_item *item = pj_ioqueue_get_user_data(key);
+    
+    //TRACE_((THIS_FILE, "     write complete: sent = %d", bytes_sent));
+
+    if (thread_quit_flag)
+        return;
+
+    item->has_pending_send = 0;
+    item->bytes_sent += bytes_sent;
+
+    if (bytes_sent <= 0) {
+        PJ_LOG(3,(THIS_FILE, "...error: sending stopped. bytes_sent=%d", 
+                  bytes_sent));
+    } 
+    else {
+        pj_status_t rc;
+
+        bytes_sent = item->buffer_size;
+        rc = pj_ioqueue_send( item->client_key, op_key,
+                              item->outgoing_buffer, &bytes_sent, 0);
+        if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
+            app_perror("...error: write error", rc);
+        }
+
+        item->has_pending_send = (rc==PJ_EPENDING);
+    }
+}
+
+/* The worker thread. */
+static int worker_thread(void *arg)
+{
+    pj_ioqueue_t *ioqueue = arg;
+    const pj_time_val timeout = {0, 100};
+    int rc;
+
+    while (!thread_quit_flag) {
+        rc = pj_ioqueue_poll(ioqueue, &timeout);
+	//TRACE_((THIS_FILE, "     thread: poll returned rc=%d", rc));
+        if (rc < 0) {
+            app_perror("...error in pj_ioqueue_poll()", pj_get_netos_error());
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/* Calculate the bandwidth for the specific test configuration.
+ * The test is simple:
+ *  - create sockpair_cnt number of producer-consumer socket pair.
+ *  - create thread_cnt number of worker threads.
+ *  - each producer will send buffer_size bytes data as fast and
+ *    as soon as it can.
+ *  - each consumer will read buffer_size bytes of data as fast 
+ *    as it could.
+ *  - measure the total bytes received by all consumers during a
+ *    period of time.
+ */
+static int perform_test(int sock_type, const char *type_name,
+                        unsigned thread_cnt, unsigned sockpair_cnt,
+                        pj_size_t buffer_size, 
+                        pj_size_t *p_bandwidth)
+{
+    enum { MSEC_DURATION = 5000 };
+    pj_pool_t *pool;
+    test_item *items;
+    pj_thread_t **thread;
+    pj_ioqueue_t *ioqueue;
+    pj_status_t rc;
+    pj_ioqueue_callback ioqueue_callback;
+    pj_uint32_t total_elapsed_usec, total_received;
+    pj_highprec_t bandwidth;
+    pj_timestamp start, stop;
+    unsigned i;
+
+    TRACE_((THIS_FILE, "    starting test.."));
+
+    ioqueue_callback.on_read_complete = &on_read_complete;
+    ioqueue_callback.on_write_complete = &on_write_complete;
+
+    thread_quit_flag = 0;
+
+    pool = pj_pool_create(mem, NULL, 4096, 4096, NULL);
+    if (!pool)
+        return -10;
+
+    items = pj_pool_alloc(pool, sockpair_cnt*sizeof(test_item));
+    thread = pj_pool_alloc(pool, thread_cnt*sizeof(pj_thread_t*));
+
+    TRACE_((THIS_FILE, "     creating ioqueue.."));
+    rc = pj_ioqueue_create(pool, sockpair_cnt*2, &ioqueue);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error: unable to create ioqueue", rc);
+        return -15;
+    }
+
+    /* Initialize each producer-consumer pair. */
+    for (i=0; i<sockpair_cnt; ++i) {
+        pj_ssize_t bytes;
+
+        items[i].ioqueue = ioqueue;
+        items[i].buffer_size = buffer_size;
+        items[i].outgoing_buffer = pj_pool_alloc(pool, buffer_size);
+        items[i].incoming_buffer = pj_pool_alloc(pool, buffer_size);
+        items[i].bytes_recv = items[i].bytes_sent = 0;
+
+        /* randomize outgoing buffer. */
+        pj_create_random_string(items[i].outgoing_buffer, buffer_size);
+
+        /* Create socket pair. */
+	TRACE_((THIS_FILE, "      calling socketpair.."));
+        rc = app_socketpair(PJ_AF_INET, sock_type, 0, 
+                            &items[i].server_fd, &items[i].client_fd);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error: unable to create socket pair", rc);
+            return -20;
+        }
+
+        /* Register server socket to ioqueue. */
+	TRACE_((THIS_FILE, "      register(1).."));
+        rc = pj_ioqueue_register_sock(pool, ioqueue, 
+                                      items[i].server_fd,
+                                      &items[i], &ioqueue_callback,
+                                      &items[i].server_key);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error: registering server socket to ioqueue", rc);
+            return -60;
+        }
+
+        /* Register client socket to ioqueue. */
+	TRACE_((THIS_FILE, "      register(2).."));
+        rc = pj_ioqueue_register_sock(pool, ioqueue, 
+                                      items[i].client_fd,
+                                      &items[i],  &ioqueue_callback,
+                                      &items[i].client_key);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error: registering server socket to ioqueue", rc);
+            return -70;
+        }
+
+        /* Start reading. */
+	TRACE_((THIS_FILE, "      pj_ioqueue_recv.."));
+        bytes = items[i].buffer_size;
+        rc = pj_ioqueue_recv(items[i].server_key, &items[i].recv_op,
+                             items[i].incoming_buffer, &bytes,
+			     0);
+        if (rc != PJ_EPENDING) {
+            app_perror("...error: pj_ioqueue_recv", rc);
+            return -73;
+        }
+
+        /* Start writing. */
+	TRACE_((THIS_FILE, "      pj_ioqueue_write.."));
+        bytes = items[i].buffer_size;
+        rc = pj_ioqueue_send(items[i].client_key, &items[i].recv_op,
+                             items[i].outgoing_buffer, &bytes, 0);
+        if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
+            app_perror("...error: pj_ioqueue_write", rc);
+            return -76;
+        }
+
+        items[i].has_pending_send = (rc==PJ_EPENDING);
+    }
+
+    /* Create the threads. */
+    for (i=0; i<thread_cnt; ++i) {
+        rc = pj_thread_create( pool, NULL, 
+                               &worker_thread, 
+                               ioqueue, 
+                               PJ_THREAD_DEFAULT_STACK_SIZE, 
+                               PJ_THREAD_SUSPENDED, &thread[i] );
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error: unable to create thread", rc);
+            return -80;
+        }
+    }
+
+    /* Mark start time. */
+    rc = pj_get_timestamp(&start);
+    if (rc != PJ_SUCCESS)
+        return -90;
+
+    /* Start the thread. */
+    TRACE_((THIS_FILE, "     resuming all threads.."));
+    for (i=0; i<thread_cnt; ++i) {
+        rc = pj_thread_resume(thread[i]);
+        if (rc != 0)
+            return -100;
+    }
+
+    /* Wait for MSEC_DURATION seconds. 
+     * This should be as simple as pj_thread_sleep(MSEC_DURATION) actually,
+     * but unfortunately it doesn't work when system doesn't employ
+     * timeslicing for threads.
+     */
+    TRACE_((THIS_FILE, "     wait for few seconds.."));
+    do {
+	pj_thread_sleep(1);
+
+	/* Mark end time. */
+	rc = pj_get_timestamp(&stop);
+
+	if (thread_quit_flag) {
+	    TRACE_((THIS_FILE, "      transfer limit reached.."));
+	    break;
+	}
+
+	if (pj_elapsed_usec(&start,&stop)<MSEC_DURATION * 1000) {
+	    TRACE_((THIS_FILE, "      time limit reached.."));
+	    break;
+	}
+
+    } while (1);
+
+    /* Terminate all threads. */
+    TRACE_((THIS_FILE, "     terminating all threads.."));
+    thread_quit_flag = 1;
+
+    for (i=0; i<thread_cnt; ++i) {
+	TRACE_((THIS_FILE, "      join thread %d..", i));
+        pj_thread_join(thread[i]);
+        pj_thread_destroy(thread[i]);
+    }
+
+    /* Close all sockets. */
+    TRACE_((THIS_FILE, "     closing all sockets.."));
+    for (i=0; i<sockpair_cnt; ++i) {
+        pj_ioqueue_unregister(items[i].server_key);
+        pj_ioqueue_unregister(items[i].client_key);
+        pj_sock_close(items[i].server_fd);
+        pj_sock_close(items[i].client_fd);
+    }
+
+    /* Destroy ioqueue. */
+    TRACE_((THIS_FILE, "     destroying ioqueue.."));
+    pj_ioqueue_destroy(ioqueue);
+
+    /* Calculate actual time in usec. */
+    total_elapsed_usec = pj_elapsed_usec(&start, &stop);
+
+    /* Calculate total bytes received. */
+    total_received = 0;
+    for (i=0; i<sockpair_cnt; ++i) {
+        total_received = items[i].bytes_recv;
+    }
+
+    /* bandwidth = total_received*1000/total_elapsed_usec */
+    bandwidth = total_received;
+    pj_highprec_mul(bandwidth, 1000);
+    pj_highprec_div(bandwidth, total_elapsed_usec);
+    
+    *p_bandwidth = (pj_uint32_t)bandwidth;
+
+    PJ_LOG(3,(THIS_FILE, "   %.4s    %d         %d        %3d us  %8d KB/s",
+              type_name, thread_cnt, sockpair_cnt,
+              -1 /*total_elapsed_usec/sockpair_cnt*/,
+              *p_bandwidth));
+
+    /* Done. */
+    pj_pool_release(pool);
+
+    TRACE_((THIS_FILE, "    done.."));
+    return 0;
+}
+
+/*
+ * main test entry.
+ */
+int ioqueue_perf_test(void)
+{
+    enum { BUF_SIZE = 512 };
+    int i, rc;
+    struct {
+        int         type;
+        const char *type_name;
+        int         thread_cnt;
+        int         sockpair_cnt;
+    } test_param[] = 
+    {
+        { PJ_SOCK_DGRAM, "udp", 1, 1},
+        { PJ_SOCK_DGRAM, "udp", 1, 2},
+        { PJ_SOCK_DGRAM, "udp", 1, 4},
+        { PJ_SOCK_DGRAM, "udp", 1, 8},
+        { PJ_SOCK_DGRAM, "udp", 2, 1},
+        { PJ_SOCK_DGRAM, "udp", 2, 2},
+        { PJ_SOCK_DGRAM, "udp", 2, 4},
+        { PJ_SOCK_DGRAM, "udp", 2, 8},
+        { PJ_SOCK_DGRAM, "udp", 4, 1},
+        { PJ_SOCK_DGRAM, "udp", 4, 2},
+        { PJ_SOCK_DGRAM, "udp", 4, 4},
+        { PJ_SOCK_DGRAM, "udp", 4, 8},
+        { PJ_SOCK_STREAM, "tcp", 1, 1},
+        { PJ_SOCK_STREAM, "tcp", 1, 2},
+        { PJ_SOCK_STREAM, "tcp", 1, 4},
+        { PJ_SOCK_STREAM, "tcp", 1, 8},
+        { PJ_SOCK_STREAM, "tcp", 2, 1},
+        { PJ_SOCK_STREAM, "tcp", 2, 2},
+        { PJ_SOCK_STREAM, "tcp", 2, 4},
+        { PJ_SOCK_STREAM, "tcp", 2, 8},
+        { PJ_SOCK_STREAM, "tcp", 4, 1},
+        { PJ_SOCK_STREAM, "tcp", 4, 2},
+        { PJ_SOCK_STREAM, "tcp", 4, 4},
+        { PJ_SOCK_STREAM, "tcp", 4, 8},
+    };
+    pj_size_t best_bandwidth;
+    int best_index = 0;
+
+    PJ_LOG(3,(THIS_FILE, "   Benchmarking %s ioqueue:", pj_ioqueue_name()));
+    PJ_LOG(3,(THIS_FILE, "   ==============================================="));
+    PJ_LOG(3,(THIS_FILE, "   Type  Threads  Skt.Pairs  Avg.Time    Bandwidth"));
+    PJ_LOG(3,(THIS_FILE, "   ==============================================="));
+
+    best_bandwidth = 0;
+    for (i=0; i<sizeof(test_param)/sizeof(test_param[0]); ++i) {
+        pj_size_t bandwidth;
+
+        rc = perform_test(test_param[i].type, 
+                          test_param[i].type_name,
+                          test_param[i].thread_cnt, 
+                          test_param[i].sockpair_cnt, 
+                          BUF_SIZE, 
+                          &bandwidth);
+        if (rc != 0)
+            return rc;
+
+        if (bandwidth > best_bandwidth)
+            best_bandwidth = bandwidth, best_index = i;
+
+        /* Give it a rest before next test. */
+        pj_thread_sleep(500);
+    }
+
+    PJ_LOG(3,(THIS_FILE, 
+              "   Best: Type=%s Threads=%d, Skt.Pairs=%d, Bandwidth=%u KB/s",
+              test_param[best_index].type_name,
+              test_param[best_index].thread_cnt,
+              test_param[best_index].sockpair_cnt,
+              best_bandwidth));
+    PJ_LOG(3,(THIS_FILE, "   (Note: packet size=%d, total errors=%u)", 
+			 BUF_SIZE, last_error_counter));
+    return 0;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_uiq_perf_test;
+#endif  /* INCLUDE_IOQUEUE_PERF_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/ioq_tcp.c b/pjlib/src/pjlib-test/ioq_tcp.c
index ade37ec..c60d614 100644
--- a/pjlib/src/pjlib-test/ioq_tcp.c
+++ b/pjlib/src/pjlib-test/ioq_tcp.c
@@ -1,540 +1,540 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-/**

- * \page page_pjlib_ioqueue_tcp_test Test: I/O Queue (TCP)

- *

- * This file provides implementation to test the

- * functionality of the I/O queue when TCP socket is used.

- *

- *

- * This file is <b>pjlib-test/ioq_tcp.c</b>

- *

- * \include pjlib-test/ioq_tcp.c

- */

-

-

-#if INCLUDE_TCP_IOQUEUE_TEST

-

-#include <pjlib.h>

-

-#if PJ_HAS_TCP

-

-#define THIS_FILE	    "test_tcp"

-#define PORT		    50000

-#define NON_EXISTANT_PORT   50123

-#define LOOP		    100

-#define BUF_MIN_SIZE	    32

-#define BUF_MAX_SIZE	    2048

-#define SOCK_INACTIVE_MIN   (4-2)

-#define SOCK_INACTIVE_MAX   (PJ_IOQUEUE_MAX_HANDLES - 2)

-#define POOL_SIZE	    (2*BUF_MAX_SIZE + SOCK_INACTIVE_MAX*128 + 2048)

-

-static pj_ssize_t	     callback_read_size,

-                             callback_write_size,

-                             callback_accept_status,

-                             callback_connect_status;

-static pj_ioqueue_key_t     *callback_read_key,

-                            *callback_write_key,

-                            *callback_accept_key,

-                            *callback_connect_key;

-static pj_ioqueue_op_key_t  *callback_read_op,

-                            *callback_write_op,

-                            *callback_accept_op;

-

-static void on_ioqueue_read(pj_ioqueue_key_t *key, 

-                            pj_ioqueue_op_key_t *op_key,

-                            pj_ssize_t bytes_read)

-{

-    callback_read_key = key;

-    callback_read_op = op_key;

-    callback_read_size = bytes_read;

-}

-

-static void on_ioqueue_write(pj_ioqueue_key_t *key, 

-                             pj_ioqueue_op_key_t *op_key,

-                             pj_ssize_t bytes_written)

-{

-    callback_write_key = key;

-    callback_write_op = op_key;

-    callback_write_size = bytes_written;

-}

-

-static void on_ioqueue_accept(pj_ioqueue_key_t *key, 

-                              pj_ioqueue_op_key_t *op_key,

-                              pj_sock_t sock, 

-                              int status)

-{

-    PJ_UNUSED_ARG(sock);

-

-    callback_accept_key = key;

-    callback_accept_op = op_key;

-    callback_accept_status = status;

-}

-

-static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status)

-{

-    callback_connect_key = key;

-    callback_connect_status = status;

-}

-

-static pj_ioqueue_callback test_cb = 

-{

-    &on_ioqueue_read,

-    &on_ioqueue_write,

-    &on_ioqueue_accept,

-    &on_ioqueue_connect,

-};

-

-static int send_recv_test(pj_ioqueue_t *ioque,

-			  pj_ioqueue_key_t *skey,

-			  pj_ioqueue_key_t *ckey,

-			  void *send_buf,

-			  void *recv_buf,

-			  pj_ssize_t bufsize,

-			  pj_timestamp *t_elapsed)

-{

-    pj_status_t status;

-    pj_ssize_t bytes;

-    pj_time_val timeout;

-    pj_timestamp t1, t2;

-    int pending_op = 0;

-    pj_ioqueue_op_key_t read_op, write_op;

-

-    // Start reading on the server side.

-    bytes = bufsize;

-    status = pj_ioqueue_recv(skey, &read_op, recv_buf, &bytes, 0);

-    if (status != PJ_SUCCESS && status != PJ_EPENDING) {

-        app_perror("...pj_ioqueue_recv error", status);

-	return -100;

-    }

-    

-    if (status == PJ_EPENDING)

-        ++pending_op;

-    else {

-        /* Does not expect to return error or immediate data. */

-        return -115;

-    }

-

-    // Randomize send buffer.

-    pj_create_random_string((char*)send_buf, bufsize);

-

-    // Starts send on the client side.

-    bytes = bufsize;

-    status = pj_ioqueue_send(ckey, &write_op, send_buf, &bytes, 0);

-    if (status != PJ_SUCCESS && bytes != PJ_EPENDING) {

-	return -120;

-    }

-    if (status == PJ_EPENDING) {

-	++pending_op;

-    }

-

-    // Begin time.

-    pj_get_timestamp(&t1);

-

-    // Reset indicators

-    callback_read_size = callback_write_size = 0;

-    callback_read_key = callback_write_key = NULL;

-    callback_read_op = callback_write_op = NULL;

-

-    // Poll the queue until we've got completion event in the server side.

-    status = 0;

-    while (pending_op > 0) {

-        timeout.sec = 1; timeout.msec = 0;

-	status = pj_ioqueue_poll(ioque, &timeout);

-	if (status > 0) {

-            if (callback_read_size) {

-                if (callback_read_size != bufsize)

-                    return -160;

-                if (callback_read_key != skey)

-                    return -161;

-                if (callback_read_op != &read_op)

-                    return -162;

-            }

-            if (callback_write_size) {

-                if (callback_write_key != ckey)

-                    return -163;

-                if (callback_write_op != &write_op)

-                    return -164;

-            }

-	    pending_op -= status;

-	}

-        if (status == 0) {

-            PJ_LOG(3,("", "...error: timed out"));

-        }

-	if (status < 0) {

-	    return -170;

-	}

-    }

-

-    // Pending op is zero.

-    // Subsequent poll should yield zero too.

-    timeout.sec = timeout.msec = 0;

-    status = pj_ioqueue_poll(ioque, &timeout);

-    if (status != 0)

-        return -173;

-

-    // End time.

-    pj_get_timestamp(&t2);

-    t_elapsed->u32.lo += (t2.u32.lo - t1.u32.lo);

-

-    // Compare recv buffer with send buffer.

-    if (pj_memcmp(send_buf, recv_buf, bufsize) != 0) {

-	return -180;

-    }

-

-    // Success

-    return 0;

-}

-

-

-/*

- * Compliance test for success scenario.

- */

-static int compliance_test_0(void)

-{

-    pj_sock_t ssock=-1, csock0=-1, csock1=-1;

-    pj_sockaddr_in addr, client_addr, rmt_addr;

-    int client_addr_len;

-    pj_pool_t *pool = NULL;

-    char *send_buf, *recv_buf;

-    pj_ioqueue_t *ioque = NULL;

-    pj_ioqueue_key_t *skey, *ckey0, *ckey1;

-    pj_ioqueue_op_key_t accept_op;

-    int bufsize = BUF_MIN_SIZE;

-    pj_ssize_t status = -1;

-    int pending_op = 0;

-    pj_timestamp t_elapsed;

-    pj_str_t s;

-    pj_status_t rc;

-

-    // Create pool.

-    pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);

-

-    // Allocate buffers for send and receive.

-    send_buf = (char*)pj_pool_alloc(pool, bufsize);

-    recv_buf = (char*)pj_pool_alloc(pool, bufsize);

-

-    // Create server socket and client socket for connecting

-    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_STREAM, 0, &ssock);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error creating socket", rc);

-        status=-1; goto on_error;

-    }

-

-    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_STREAM, 0, &csock1);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error creating socket", rc);

-	status=-1; goto on_error;

-    }

-

-    // Bind server socket.

-    memset(&addr, 0, sizeof(addr));

-    addr.sin_family = PJ_AF_INET;

-    addr.sin_port = pj_htons(PORT);

-    if (pj_sock_bind(ssock, &addr, sizeof(addr))) {

-        app_perror("...bind error", rc);

-	status=-10; goto on_error;

-    }

-

-    // Create I/O Queue.

-    rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...ERROR in pj_ioqueue_create()", rc);

-	status=-20; goto on_error;

-    }

-

-    // Register server socket and client socket.

-    rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL, &test_cb, &skey);

-    if (rc == PJ_SUCCESS)

-        rc = pj_ioqueue_register_sock(pool, ioque, csock1, NULL, &test_cb, 

-                                      &ckey1);

-    else

-        ckey1 = NULL;

-    if (rc != PJ_SUCCESS) {

-        app_perror("...ERROR in pj_ioqueue_register_sock()", rc);

-	status=-23; goto on_error;

-    }

-

-    // Server socket listen().

-    if (pj_sock_listen(ssock, 5)) {

-        app_perror("...ERROR in pj_sock_listen()", rc);

-	status=-25; goto on_error;

-    }

-

-    // Server socket accept()

-    client_addr_len = sizeof(pj_sockaddr_in);

-    status = pj_ioqueue_accept(skey, &accept_op, &csock0, 

-                               &client_addr, &rmt_addr, &client_addr_len);

-    if (status != PJ_EPENDING) {

-        app_perror("...ERROR in pj_ioqueue_accept()", rc);

-	status=-30; goto on_error;

-    }

-    if (status==PJ_EPENDING) {

-	++pending_op;

-    }

-

-    // Initialize remote address.

-    memset(&addr, 0, sizeof(addr));

-    addr.sin_family = PJ_AF_INET;

-    addr.sin_port = pj_htons(PORT);

-    addr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));

-

-    // Client socket connect()

-    status = pj_ioqueue_connect(ckey1, &addr, sizeof(addr));

-    if (status!=PJ_SUCCESS && status != PJ_EPENDING) {

-        app_perror("...ERROR in pj_ioqueue_connect()", rc);

-	status=-40; goto on_error;

-    }

-    if (status==PJ_EPENDING) {

-	++pending_op;

-    }

-

-    // Poll until connected

-    callback_read_size = callback_write_size = 0;

-    callback_accept_status = callback_connect_status = -2;

-

-    callback_read_key = callback_write_key = 

-        callback_accept_key = callback_connect_key = NULL;

-    callback_accept_op = callback_read_op = callback_write_op = NULL;

-

-    while (pending_op) {

-	pj_time_val timeout = {1, 0};

-

-	status=pj_ioqueue_poll(ioque, &timeout);

-	if (status > 0) {

-            if (callback_accept_status != -2) {

-                if (callback_accept_status != 0) {

-                    status=-41; goto on_error;

-                }

-                if (callback_accept_key != skey) {

-                    status=-42; goto on_error;

-                }

-                if (callback_accept_op != &accept_op) {

-                    status=-43; goto on_error;

-                }

-                callback_accept_status = -2;

-            }

-

-            if (callback_connect_status != -2) {

-                if (callback_connect_status != 0) {

-                    status=-50; goto on_error;

-                }

-                if (callback_connect_key != ckey1) {

-                    status=-51; goto on_error;

-                }

-                callback_connect_status = -2;

-            }

-

-	    pending_op -= status;

-

-	    if (pending_op == 0) {

-		status = 0;

-	    }

-	}

-    }

-

-    // There's no pending operation.

-    // When we poll the ioqueue, there must not be events.

-    if (pending_op == 0) {

-        pj_time_val timeout = {1, 0};

-        status = pj_ioqueue_poll(ioque, &timeout);

-        if (status != 0) {

-            status=-60; goto on_error;

-        }

-    }

-

-    // Check accepted socket.

-    if (csock0 == PJ_INVALID_SOCKET) {

-	status = -69;

-        app_perror("...accept() error", pj_get_os_error());

-	goto on_error;

-    }

-

-    // Register newly accepted socket.

-    rc = pj_ioqueue_register_sock(pool, ioque, csock0, NULL, 

-                                  &test_cb, &ckey0);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...ERROR in pj_ioqueue_register_sock", rc);

-	status = -70;

-	goto on_error;

-    }

-

-    // Test send and receive.

-    t_elapsed.u32.lo = 0;

-    status = send_recv_test(ioque, ckey0, ckey1, send_buf, 

-                            recv_buf, bufsize, &t_elapsed);

-    if (status != 0) {

-	goto on_error;

-    }

-

-    // Success

-    status = 0;

-

-on_error:

-    if (ssock != PJ_INVALID_SOCKET)

-	pj_sock_close(ssock);

-    if (csock1 != PJ_INVALID_SOCKET)

-	pj_sock_close(csock1);

-    if (csock0 != PJ_INVALID_SOCKET)

-	pj_sock_close(csock0);

-    if (ioque != NULL)

-	pj_ioqueue_destroy(ioque);

-    pj_pool_release(pool);

-    return status;

-

-}

-

-/*

- * Compliance test for failed scenario.

- * In this case, the client connects to a non-existant service.

- */

-static int compliance_test_1(void)

-{

-    pj_sock_t csock1=-1;

-    pj_sockaddr_in addr;

-    pj_pool_t *pool = NULL;

-    pj_ioqueue_t *ioque = NULL;

-    pj_ioqueue_key_t *ckey1;

-    pj_ssize_t status = -1;

-    int pending_op = 0;

-    pj_str_t s;

-    pj_status_t rc;

-

-    // Create pool.

-    pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);

-

-    // Create I/O Queue.

-    rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);

-    if (!ioque) {

-	status=-20; goto on_error;

-    }

-

-    // Create client socket

-    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_STREAM, 0, &csock1);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...ERROR in pj_sock_socket()", rc);

-	status=-1; goto on_error;

-    }

-

-    // Register client socket.

-    rc = pj_ioqueue_register_sock(pool, ioque, csock1, NULL, 

-                                  &test_cb, &ckey1);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...ERROR in pj_ioqueue_register_sock()", rc);

-	status=-23; goto on_error;

-    }

-

-    // Initialize remote address.

-    memset(&addr, 0, sizeof(addr));

-    addr.sin_family = PJ_AF_INET;

-    addr.sin_port = pj_htons(NON_EXISTANT_PORT);

-    addr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));

-

-    // Client socket connect()

-    status = pj_ioqueue_connect(ckey1, &addr, sizeof(addr));

-    if (status==PJ_SUCCESS) {

-	// unexpectedly success!

-	status = -30;

-	goto on_error;

-    }

-    if (status != PJ_EPENDING) {

-	// success

-    } else {

-	++pending_op;

-    }

-

-    callback_connect_status = -2;

-    callback_connect_key = NULL;

-

-    // Poll until we've got result

-    while (pending_op) {

-	pj_time_val timeout = {1, 0};

-

-	status=pj_ioqueue_poll(ioque, &timeout);

-	if (status > 0) {

-            if (callback_connect_key==ckey1) {

-		if (callback_connect_status == 0) {

-		    // unexpectedly connected!

-		    status = -50;

-		    goto on_error;

-		}

-	    }

-

-	    pending_op -= status;

-	    if (pending_op == 0) {

-		status = 0;

-	    }

-	}

-    }

-

-    // There's no pending operation.

-    // When we poll the ioqueue, there must not be events.

-    if (pending_op == 0) {

-        pj_time_val timeout = {1, 0};

-        status = pj_ioqueue_poll(ioque, &timeout);

-        if (status != 0) {

-            status=-60; goto on_error;

-        }

-    }

-

-    // Success

-    status = 0;

-

-on_error:

-    if (csock1 != PJ_INVALID_SOCKET)

-	pj_sock_close(csock1);

-    if (ioque != NULL)

-	pj_ioqueue_destroy(ioque);

-    pj_pool_release(pool);

-    return status;

-}

-

-int tcp_ioqueue_test()

-{

-    int status;

-

-    PJ_LOG(3, (THIS_FILE, "..%s compliance test 0 (success scenario)",

-	       pj_ioqueue_name()));

-    if ((status=compliance_test_0()) != 0) {

-	PJ_LOG(1, (THIS_FILE, "....FAILED (status=%d)\n", status));

-	return status;

-    }

-    PJ_LOG(3, (THIS_FILE, "..%s compliance test 1 (failed scenario)",

-               pj_ioqueue_name()));

-    if ((status=compliance_test_1()) != 0) {

-	PJ_LOG(1, (THIS_FILE, "....FAILED (status=%d)\n", status));

-	return status;

-    }

-

-    return 0;

-}

-

-#endif	/* PJ_HAS_TCP */

-

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_uiq_tcp;

-#endif	/* INCLUDE_TCP_IOQUEUE_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+/**
+ * \page page_pjlib_ioqueue_tcp_test Test: I/O Queue (TCP)
+ *
+ * This file provides implementation to test the
+ * functionality of the I/O queue when TCP socket is used.
+ *
+ *
+ * This file is <b>pjlib-test/ioq_tcp.c</b>
+ *
+ * \include pjlib-test/ioq_tcp.c
+ */
+
+
+#if INCLUDE_TCP_IOQUEUE_TEST
+
+#include <pjlib.h>
+
+#if PJ_HAS_TCP
+
+#define THIS_FILE	    "test_tcp"
+#define PORT		    50000
+#define NON_EXISTANT_PORT   50123
+#define LOOP		    100
+#define BUF_MIN_SIZE	    32
+#define BUF_MAX_SIZE	    2048
+#define SOCK_INACTIVE_MIN   (4-2)
+#define SOCK_INACTIVE_MAX   (PJ_IOQUEUE_MAX_HANDLES - 2)
+#define POOL_SIZE	    (2*BUF_MAX_SIZE + SOCK_INACTIVE_MAX*128 + 2048)
+
+static pj_ssize_t	     callback_read_size,
+                             callback_write_size,
+                             callback_accept_status,
+                             callback_connect_status;
+static pj_ioqueue_key_t     *callback_read_key,
+                            *callback_write_key,
+                            *callback_accept_key,
+                            *callback_connect_key;
+static pj_ioqueue_op_key_t  *callback_read_op,
+                            *callback_write_op,
+                            *callback_accept_op;
+
+static void on_ioqueue_read(pj_ioqueue_key_t *key, 
+                            pj_ioqueue_op_key_t *op_key,
+                            pj_ssize_t bytes_read)
+{
+    callback_read_key = key;
+    callback_read_op = op_key;
+    callback_read_size = bytes_read;
+}
+
+static void on_ioqueue_write(pj_ioqueue_key_t *key, 
+                             pj_ioqueue_op_key_t *op_key,
+                             pj_ssize_t bytes_written)
+{
+    callback_write_key = key;
+    callback_write_op = op_key;
+    callback_write_size = bytes_written;
+}
+
+static void on_ioqueue_accept(pj_ioqueue_key_t *key, 
+                              pj_ioqueue_op_key_t *op_key,
+                              pj_sock_t sock, 
+                              int status)
+{
+    PJ_UNUSED_ARG(sock);
+
+    callback_accept_key = key;
+    callback_accept_op = op_key;
+    callback_accept_status = status;
+}
+
+static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status)
+{
+    callback_connect_key = key;
+    callback_connect_status = status;
+}
+
+static pj_ioqueue_callback test_cb = 
+{
+    &on_ioqueue_read,
+    &on_ioqueue_write,
+    &on_ioqueue_accept,
+    &on_ioqueue_connect,
+};
+
+static int send_recv_test(pj_ioqueue_t *ioque,
+			  pj_ioqueue_key_t *skey,
+			  pj_ioqueue_key_t *ckey,
+			  void *send_buf,
+			  void *recv_buf,
+			  pj_ssize_t bufsize,
+			  pj_timestamp *t_elapsed)
+{
+    pj_status_t status;
+    pj_ssize_t bytes;
+    pj_time_val timeout;
+    pj_timestamp t1, t2;
+    int pending_op = 0;
+    pj_ioqueue_op_key_t read_op, write_op;
+
+    // Start reading on the server side.
+    bytes = bufsize;
+    status = pj_ioqueue_recv(skey, &read_op, recv_buf, &bytes, 0);
+    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
+        app_perror("...pj_ioqueue_recv error", status);
+	return -100;
+    }
+    
+    if (status == PJ_EPENDING)
+        ++pending_op;
+    else {
+        /* Does not expect to return error or immediate data. */
+        return -115;
+    }
+
+    // Randomize send buffer.
+    pj_create_random_string((char*)send_buf, bufsize);
+
+    // Starts send on the client side.
+    bytes = bufsize;
+    status = pj_ioqueue_send(ckey, &write_op, send_buf, &bytes, 0);
+    if (status != PJ_SUCCESS && bytes != PJ_EPENDING) {
+	return -120;
+    }
+    if (status == PJ_EPENDING) {
+	++pending_op;
+    }
+
+    // Begin time.
+    pj_get_timestamp(&t1);
+
+    // Reset indicators
+    callback_read_size = callback_write_size = 0;
+    callback_read_key = callback_write_key = NULL;
+    callback_read_op = callback_write_op = NULL;
+
+    // Poll the queue until we've got completion event in the server side.
+    status = 0;
+    while (pending_op > 0) {
+        timeout.sec = 1; timeout.msec = 0;
+	status = pj_ioqueue_poll(ioque, &timeout);
+	if (status > 0) {
+            if (callback_read_size) {
+                if (callback_read_size != bufsize)
+                    return -160;
+                if (callback_read_key != skey)
+                    return -161;
+                if (callback_read_op != &read_op)
+                    return -162;
+            }
+            if (callback_write_size) {
+                if (callback_write_key != ckey)
+                    return -163;
+                if (callback_write_op != &write_op)
+                    return -164;
+            }
+	    pending_op -= status;
+	}
+        if (status == 0) {
+            PJ_LOG(3,("", "...error: timed out"));
+        }
+	if (status < 0) {
+	    return -170;
+	}
+    }
+
+    // Pending op is zero.
+    // Subsequent poll should yield zero too.
+    timeout.sec = timeout.msec = 0;
+    status = pj_ioqueue_poll(ioque, &timeout);
+    if (status != 0)
+        return -173;
+
+    // End time.
+    pj_get_timestamp(&t2);
+    t_elapsed->u32.lo += (t2.u32.lo - t1.u32.lo);
+
+    // Compare recv buffer with send buffer.
+    if (pj_memcmp(send_buf, recv_buf, bufsize) != 0) {
+	return -180;
+    }
+
+    // Success
+    return 0;
+}
+
+
+/*
+ * Compliance test for success scenario.
+ */
+static int compliance_test_0(void)
+{
+    pj_sock_t ssock=-1, csock0=-1, csock1=-1;
+    pj_sockaddr_in addr, client_addr, rmt_addr;
+    int client_addr_len;
+    pj_pool_t *pool = NULL;
+    char *send_buf, *recv_buf;
+    pj_ioqueue_t *ioque = NULL;
+    pj_ioqueue_key_t *skey, *ckey0, *ckey1;
+    pj_ioqueue_op_key_t accept_op;
+    int bufsize = BUF_MIN_SIZE;
+    pj_ssize_t status = -1;
+    int pending_op = 0;
+    pj_timestamp t_elapsed;
+    pj_str_t s;
+    pj_status_t rc;
+
+    // Create pool.
+    pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);
+
+    // Allocate buffers for send and receive.
+    send_buf = (char*)pj_pool_alloc(pool, bufsize);
+    recv_buf = (char*)pj_pool_alloc(pool, bufsize);
+
+    // Create server socket and client socket for connecting
+    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_STREAM, 0, &ssock);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error creating socket", rc);
+        status=-1; goto on_error;
+    }
+
+    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_STREAM, 0, &csock1);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error creating socket", rc);
+	status=-1; goto on_error;
+    }
+
+    // Bind server socket.
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = PJ_AF_INET;
+    addr.sin_port = pj_htons(PORT);
+    if (pj_sock_bind(ssock, &addr, sizeof(addr))) {
+        app_perror("...bind error", rc);
+	status=-10; goto on_error;
+    }
+
+    // Create I/O Queue.
+    rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...ERROR in pj_ioqueue_create()", rc);
+	status=-20; goto on_error;
+    }
+
+    // Register server socket and client socket.
+    rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL, &test_cb, &skey);
+    if (rc == PJ_SUCCESS)
+        rc = pj_ioqueue_register_sock(pool, ioque, csock1, NULL, &test_cb, 
+                                      &ckey1);
+    else
+        ckey1 = NULL;
+    if (rc != PJ_SUCCESS) {
+        app_perror("...ERROR in pj_ioqueue_register_sock()", rc);
+	status=-23; goto on_error;
+    }
+
+    // Server socket listen().
+    if (pj_sock_listen(ssock, 5)) {
+        app_perror("...ERROR in pj_sock_listen()", rc);
+	status=-25; goto on_error;
+    }
+
+    // Server socket accept()
+    client_addr_len = sizeof(pj_sockaddr_in);
+    status = pj_ioqueue_accept(skey, &accept_op, &csock0, 
+                               &client_addr, &rmt_addr, &client_addr_len);
+    if (status != PJ_EPENDING) {
+        app_perror("...ERROR in pj_ioqueue_accept()", rc);
+	status=-30; goto on_error;
+    }
+    if (status==PJ_EPENDING) {
+	++pending_op;
+    }
+
+    // Initialize remote address.
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = PJ_AF_INET;
+    addr.sin_port = pj_htons(PORT);
+    addr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));
+
+    // Client socket connect()
+    status = pj_ioqueue_connect(ckey1, &addr, sizeof(addr));
+    if (status!=PJ_SUCCESS && status != PJ_EPENDING) {
+        app_perror("...ERROR in pj_ioqueue_connect()", rc);
+	status=-40; goto on_error;
+    }
+    if (status==PJ_EPENDING) {
+	++pending_op;
+    }
+
+    // Poll until connected
+    callback_read_size = callback_write_size = 0;
+    callback_accept_status = callback_connect_status = -2;
+
+    callback_read_key = callback_write_key = 
+        callback_accept_key = callback_connect_key = NULL;
+    callback_accept_op = callback_read_op = callback_write_op = NULL;
+
+    while (pending_op) {
+	pj_time_val timeout = {1, 0};
+
+	status=pj_ioqueue_poll(ioque, &timeout);
+	if (status > 0) {
+            if (callback_accept_status != -2) {
+                if (callback_accept_status != 0) {
+                    status=-41; goto on_error;
+                }
+                if (callback_accept_key != skey) {
+                    status=-42; goto on_error;
+                }
+                if (callback_accept_op != &accept_op) {
+                    status=-43; goto on_error;
+                }
+                callback_accept_status = -2;
+            }
+
+            if (callback_connect_status != -2) {
+                if (callback_connect_status != 0) {
+                    status=-50; goto on_error;
+                }
+                if (callback_connect_key != ckey1) {
+                    status=-51; goto on_error;
+                }
+                callback_connect_status = -2;
+            }
+
+	    pending_op -= status;
+
+	    if (pending_op == 0) {
+		status = 0;
+	    }
+	}
+    }
+
+    // There's no pending operation.
+    // When we poll the ioqueue, there must not be events.
+    if (pending_op == 0) {
+        pj_time_val timeout = {1, 0};
+        status = pj_ioqueue_poll(ioque, &timeout);
+        if (status != 0) {
+            status=-60; goto on_error;
+        }
+    }
+
+    // Check accepted socket.
+    if (csock0 == PJ_INVALID_SOCKET) {
+	status = -69;
+        app_perror("...accept() error", pj_get_os_error());
+	goto on_error;
+    }
+
+    // Register newly accepted socket.
+    rc = pj_ioqueue_register_sock(pool, ioque, csock0, NULL, 
+                                  &test_cb, &ckey0);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...ERROR in pj_ioqueue_register_sock", rc);
+	status = -70;
+	goto on_error;
+    }
+
+    // Test send and receive.
+    t_elapsed.u32.lo = 0;
+    status = send_recv_test(ioque, ckey0, ckey1, send_buf, 
+                            recv_buf, bufsize, &t_elapsed);
+    if (status != 0) {
+	goto on_error;
+    }
+
+    // Success
+    status = 0;
+
+on_error:
+    if (ssock != PJ_INVALID_SOCKET)
+	pj_sock_close(ssock);
+    if (csock1 != PJ_INVALID_SOCKET)
+	pj_sock_close(csock1);
+    if (csock0 != PJ_INVALID_SOCKET)
+	pj_sock_close(csock0);
+    if (ioque != NULL)
+	pj_ioqueue_destroy(ioque);
+    pj_pool_release(pool);
+    return status;
+
+}
+
+/*
+ * Compliance test for failed scenario.
+ * In this case, the client connects to a non-existant service.
+ */
+static int compliance_test_1(void)
+{
+    pj_sock_t csock1=-1;
+    pj_sockaddr_in addr;
+    pj_pool_t *pool = NULL;
+    pj_ioqueue_t *ioque = NULL;
+    pj_ioqueue_key_t *ckey1;
+    pj_ssize_t status = -1;
+    int pending_op = 0;
+    pj_str_t s;
+    pj_status_t rc;
+
+    // Create pool.
+    pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);
+
+    // Create I/O Queue.
+    rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);
+    if (!ioque) {
+	status=-20; goto on_error;
+    }
+
+    // Create client socket
+    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_STREAM, 0, &csock1);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...ERROR in pj_sock_socket()", rc);
+	status=-1; goto on_error;
+    }
+
+    // Register client socket.
+    rc = pj_ioqueue_register_sock(pool, ioque, csock1, NULL, 
+                                  &test_cb, &ckey1);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...ERROR in pj_ioqueue_register_sock()", rc);
+	status=-23; goto on_error;
+    }
+
+    // Initialize remote address.
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = PJ_AF_INET;
+    addr.sin_port = pj_htons(NON_EXISTANT_PORT);
+    addr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));
+
+    // Client socket connect()
+    status = pj_ioqueue_connect(ckey1, &addr, sizeof(addr));
+    if (status==PJ_SUCCESS) {
+	// unexpectedly success!
+	status = -30;
+	goto on_error;
+    }
+    if (status != PJ_EPENDING) {
+	// success
+    } else {
+	++pending_op;
+    }
+
+    callback_connect_status = -2;
+    callback_connect_key = NULL;
+
+    // Poll until we've got result
+    while (pending_op) {
+	pj_time_val timeout = {1, 0};
+
+	status=pj_ioqueue_poll(ioque, &timeout);
+	if (status > 0) {
+            if (callback_connect_key==ckey1) {
+		if (callback_connect_status == 0) {
+		    // unexpectedly connected!
+		    status = -50;
+		    goto on_error;
+		}
+	    }
+
+	    pending_op -= status;
+	    if (pending_op == 0) {
+		status = 0;
+	    }
+	}
+    }
+
+    // There's no pending operation.
+    // When we poll the ioqueue, there must not be events.
+    if (pending_op == 0) {
+        pj_time_val timeout = {1, 0};
+        status = pj_ioqueue_poll(ioque, &timeout);
+        if (status != 0) {
+            status=-60; goto on_error;
+        }
+    }
+
+    // Success
+    status = 0;
+
+on_error:
+    if (csock1 != PJ_INVALID_SOCKET)
+	pj_sock_close(csock1);
+    if (ioque != NULL)
+	pj_ioqueue_destroy(ioque);
+    pj_pool_release(pool);
+    return status;
+}
+
+int tcp_ioqueue_test()
+{
+    int status;
+
+    PJ_LOG(3, (THIS_FILE, "..%s compliance test 0 (success scenario)",
+	       pj_ioqueue_name()));
+    if ((status=compliance_test_0()) != 0) {
+	PJ_LOG(1, (THIS_FILE, "....FAILED (status=%d)\n", status));
+	return status;
+    }
+    PJ_LOG(3, (THIS_FILE, "..%s compliance test 1 (failed scenario)",
+               pj_ioqueue_name()));
+    if ((status=compliance_test_1()) != 0) {
+	PJ_LOG(1, (THIS_FILE, "....FAILED (status=%d)\n", status));
+	return status;
+    }
+
+    return 0;
+}
+
+#endif	/* PJ_HAS_TCP */
+
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_uiq_tcp;
+#endif	/* INCLUDE_TCP_IOQUEUE_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/ioq_udp.c b/pjlib/src/pjlib-test/ioq_udp.c
index 1e3b6dc..7db2a8e 100644
--- a/pjlib/src/pjlib-test/ioq_udp.c
+++ b/pjlib/src/pjlib-test/ioq_udp.c
@@ -1,663 +1,663 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-

-/**

- * \page page_pjlib_ioqueue_udp_test Test: I/O Queue (UDP)

- *

- * This file provides implementation to test the

- * functionality of the I/O queue when UDP socket is used.

- *

- *

- * This file is <b>pjlib-test/ioq_udp.c</b>

- *

- * \include pjlib-test/ioq_udp.c

- */

-

-

-#if INCLUDE_UDP_IOQUEUE_TEST

-

-#include <pjlib.h>

-

-#include <pj/compat/socket.h>

-

-#define THIS_FILE	    "test_udp"

-#define PORT		    51233

-#define LOOP		    100

-#define BUF_MIN_SIZE	    32

-#define BUF_MAX_SIZE	    2048

-#define SOCK_INACTIVE_MIN   (1)

-#define SOCK_INACTIVE_MAX   (PJ_IOQUEUE_MAX_HANDLES - 2)

-#define POOL_SIZE	    (2*BUF_MAX_SIZE + SOCK_INACTIVE_MAX*128 + 2048)

-

-#undef TRACE_

-#define TRACE_(msg)	    PJ_LOG(3,(THIS_FILE,"....." msg))

-

-static pj_ssize_t            callback_read_size,

-                             callback_write_size,

-                             callback_accept_status,

-                             callback_connect_status;

-static pj_ioqueue_key_t     *callback_read_key,

-                            *callback_write_key,

-                            *callback_accept_key,

-                            *callback_connect_key;

-static pj_ioqueue_op_key_t  *callback_read_op,

-                            *callback_write_op,

-                            *callback_accept_op;

-

-static void on_ioqueue_read(pj_ioqueue_key_t *key, 

-                            pj_ioqueue_op_key_t *op_key,

-                            pj_ssize_t bytes_read)

-{

-    callback_read_key = key;

-    callback_read_op = op_key;

-    callback_read_size = bytes_read;

-}

-

-static void on_ioqueue_write(pj_ioqueue_key_t *key, 

-                             pj_ioqueue_op_key_t *op_key,

-                             pj_ssize_t bytes_written)

-{

-    callback_write_key = key;

-    callback_write_op = op_key;

-    callback_write_size = bytes_written;

-}

-

-static void on_ioqueue_accept(pj_ioqueue_key_t *key, 

-                              pj_ioqueue_op_key_t *op_key,

-                              pj_sock_t sock, int status)

-{

-    PJ_UNUSED_ARG(sock);

-    callback_accept_key = key;

-    callback_accept_op = op_key;

-    callback_accept_status = status;

-}

-

-static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status)

-{

-    callback_connect_key = key;

-    callback_connect_status = status;

-}

-

-static pj_ioqueue_callback test_cb = 

-{

-    &on_ioqueue_read,

-    &on_ioqueue_write,

-    &on_ioqueue_accept,

-    &on_ioqueue_connect,

-};

-

-#ifdef PJ_WIN32

-#  define S_ADDR S_un.S_addr

-#else

-#  define S_ADDR s_addr

-#endif

-

-/*

- * compliance_test()

- * To test that the basic IOQueue functionality works. It will just exchange

- * data between two sockets.

- */ 

-static int compliance_test(void)

-{

-    pj_sock_t ssock=-1, csock=-1;

-    pj_sockaddr_in addr;

-    int addrlen;

-    pj_pool_t *pool = NULL;

-    char *send_buf, *recv_buf;

-    pj_ioqueue_t *ioque = NULL;

-    pj_ioqueue_key_t *skey, *ckey;

-    pj_ioqueue_op_key_t read_op, write_op;

-    int bufsize = BUF_MIN_SIZE;

-    pj_ssize_t bytes, status = -1;

-    pj_str_t temp;

-    pj_bool_t send_pending, recv_pending;

-    pj_status_t rc;

-

-    pj_set_os_error(PJ_SUCCESS);

-

-    // Create pool.

-    pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);

-

-    // Allocate buffers for send and receive.

-    send_buf = (char*)pj_pool_alloc(pool, bufsize);

-    recv_buf = (char*)pj_pool_alloc(pool, bufsize);

-

-    // Allocate sockets for sending and receiving.

-    TRACE_("creating sockets...");

-    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &ssock);

-    if (rc==PJ_SUCCESS)

-        rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &csock);

-    else

-        csock = PJ_INVALID_SOCKET;

-    if (rc != PJ_SUCCESS) {

-        app_perror("...ERROR in pj_sock_socket()", rc);

-	status=-1; goto on_error;

-    }

-

-    // Bind server socket.

-    TRACE_("bind socket...");

-    memset(&addr, 0, sizeof(addr));

-    addr.sin_family = PJ_AF_INET;

-    addr.sin_port = pj_htons(PORT);

-    if (pj_sock_bind(ssock, &addr, sizeof(addr))) {

-	status=-10; goto on_error;

-    }

-

-    // Create I/O Queue.

-    TRACE_("create ioqueue...");

-    rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);

-    if (rc != PJ_SUCCESS) {

-	status=-20; goto on_error;

-    }

-

-    // Register server and client socket.

-    // We put this after inactivity socket, hopefully this can represent the

-    // worst waiting time.

-    TRACE_("registering first sockets...");

-    rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL, 

-			          &test_cb, &skey);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error(10): ioqueue_register error", rc);

-	status=-25; goto on_error;

-    }

-    TRACE_("registering second sockets...");

-    rc = pj_ioqueue_register_sock( pool, ioque, csock, NULL, 

-			           &test_cb, &ckey);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error(11): ioqueue_register error", rc);

-	status=-26; goto on_error;

-    }

-

-    // Set destination address to send the packet.

-    TRACE_("set destination address...");

-    temp = pj_str("127.0.0.1");

-    if ((rc=pj_sockaddr_in_init(&addr, &temp, PORT)) != 0) {

-	app_perror("...error: unable to resolve 127.0.0.1", rc);

-	status=-26; goto on_error;

-    }

-

-    // Randomize send_buf.

-    pj_create_random_string(send_buf, bufsize);

-

-    // Register reading from ioqueue.

-    TRACE_("start recvfrom...");

-    addrlen = sizeof(addr);

-    bytes = bufsize;

-    rc = pj_ioqueue_recvfrom(skey, &read_op, recv_buf, &bytes, 0,

-			     &addr, &addrlen);

-    if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {

-        app_perror("...error: pj_ioqueue_recvfrom", rc);

-	status=-28; goto on_error;

-    } else if (rc == PJ_EPENDING) {

-	recv_pending = 1;

-	PJ_LOG(3, (THIS_FILE, 

-		   "......ok: recvfrom returned pending"));

-    } else {

-	PJ_LOG(3, (THIS_FILE, 

-		   "......error: recvfrom returned immediate ok!"));

-	status=-29; goto on_error;

-    }

-

-    // Write must return the number of bytes.

-    TRACE_("start sendto...");

-    bytes = bufsize;

-    rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0, &addr, 

-			   sizeof(addr));

-    if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {

-        app_perror("...error: pj_ioqueue_sendto", rc);

-	status=-30; goto on_error;

-    } else if (rc == PJ_EPENDING) {

-	send_pending = 1;

-	PJ_LOG(3, (THIS_FILE, 

-		   "......ok: sendto returned pending"));

-    } else {

-	send_pending = 0;

-	PJ_LOG(3, (THIS_FILE, 

-		   "......ok: sendto returned immediate success"));

-    }

-

-    // reset callback variables.

-    callback_read_size = callback_write_size = 0;

-    callback_accept_status = callback_connect_status = -2;

-    callback_read_key = callback_write_key = 

-        callback_accept_key = callback_connect_key = NULL;

-    callback_read_op = callback_write_op = NULL;

-

-    // Poll if pending.

-    while (send_pending || recv_pending) {

-	int rc;

-	pj_time_val timeout = { 5, 0 };

-

-	TRACE_("poll...");

-	rc = pj_ioqueue_poll(ioque, &timeout);

-

-	if (rc == 0) {

-	    PJ_LOG(1,(THIS_FILE, "...ERROR: timed out..."));

-	    status=-45; goto on_error;

-        } else if (rc < 0) {

-            app_perror("...ERROR in ioqueue_poll()", rc);

-	    status=-50; goto on_error;

-	}

-

-	if (callback_read_key != NULL) {

-            if (callback_read_size != bufsize) {

-                status=-61; goto on_error;

-            }

-            if (callback_read_key != skey) {

-                status=-65; goto on_error;

-            }

-            if (callback_read_op != &read_op) {

-                status=-66; goto on_error;

-            }

-

-	    if (memcmp(send_buf, recv_buf, bufsize) != 0) {

-		status=-70; goto on_error;

-	    }

-

-

-	    recv_pending = 0;

-	} 

-

-        if (callback_write_key != NULL) {

-            if (callback_write_size != bufsize) {

-                status=-73; goto on_error;

-            }

-            if (callback_write_key != ckey) {

-                status=-75; goto on_error;

-            }

-            if (callback_write_op != &write_op) {

-                status=-76; goto on_error;

-            }

-

-            send_pending = 0;

-	}

-    } 

-    

-    // Success

-    status = 0;

-

-on_error:

-    if (status != 0) {

-	char errbuf[128];

-	PJ_LOG(1, (THIS_FILE, 

-		   "...compliance test error: status=%d, os_err=%d (%s)", 

-		   status, pj_get_netos_error(),

-	           pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf))));

-    }

-    if (ssock)

-	pj_sock_close(ssock);

-    if (csock)

-	pj_sock_close(csock);

-    if (ioque != NULL)

-	pj_ioqueue_destroy(ioque);

-    pj_pool_release(pool);

-    return status;

-

-}

-

-/*

- * Testing with many handles.

- * This will just test registering PJ_IOQUEUE_MAX_HANDLES count

- * of sockets to the ioqueue.

- */

-static int many_handles_test(void)

-{

-    enum { MAX = PJ_IOQUEUE_MAX_HANDLES };

-    pj_pool_t *pool;

-    pj_ioqueue_t *ioqueue;

-    pj_sock_t *sock;

-    pj_ioqueue_key_t **key;

-    pj_status_t rc;

-    int count, i;

-

-    PJ_LOG(3,(THIS_FILE,"...testing with so many handles"));

-

-    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);

-    if (!pool)

-	return PJ_ENOMEM;

-

-    key = pj_pool_alloc(pool, MAX*sizeof(pj_ioqueue_key_t*));

-    sock = pj_pool_alloc(pool, MAX*sizeof(pj_sock_t));

-    

-    /* Create IOQueue */

-    rc = pj_ioqueue_create(pool, MAX, &ioqueue);

-    if (rc != PJ_SUCCESS || ioqueue == NULL) {

-	app_perror("...error in pj_ioqueue_create", rc);

-	return -10;

-    }

-

-    /* Register as many sockets. */

-    for (count=0; count<MAX; ++count) {

-	sock[count] = PJ_INVALID_SOCKET;

-	rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[count]);

-	if (rc != PJ_SUCCESS || sock[count] == PJ_INVALID_SOCKET) {

-	    PJ_LOG(3,(THIS_FILE, "....unable to create %d-th socket, rc=%d", 

-				 count, rc));

-	    break;

-	}

-	key[count] = NULL;

-	rc = pj_ioqueue_register_sock(pool, ioqueue, sock[count],

-				      NULL, &test_cb, &key[count]);

-	if (rc != PJ_SUCCESS || key[count] == NULL) {

-	    PJ_LOG(3,(THIS_FILE, "....unable to register %d-th socket, rc=%d", 

-				 count, rc));

-	    return -30;

-	}

-    }

-

-    /* Test complete. */

-

-    /* Now deregister and close all handles. */ 

-

-    for (i=0; i<count; ++i) {

-	rc = pj_ioqueue_unregister(key[i]);

-	if (rc != PJ_SUCCESS) {

-	    app_perror("...error in pj_ioqueue_unregister", rc);

-	}

-	rc = pj_sock_close(sock[i]);

-	if (rc != PJ_SUCCESS) {

-	    app_perror("...error in pj_sock_close", rc);

-	}

-    }

-

-    rc = pj_ioqueue_destroy(ioqueue);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error in pj_ioqueue_destroy", rc);

-    }

-    

-    pj_pool_release(pool);

-

-    PJ_LOG(3,(THIS_FILE,"....many_handles_test() ok"));

-

-    return 0;

-}

-

-/*

- * Multi-operation test.

- */

-

-/*

- * Benchmarking IOQueue

- */

-static int bench_test(int bufsize, int inactive_sock_count)

-{

-    pj_sock_t ssock=-1, csock=-1;

-    pj_sockaddr_in addr;

-    pj_pool_t *pool = NULL;

-    pj_sock_t *inactive_sock=NULL;

-    pj_ioqueue_op_key_t *inactive_read_op;

-    char *send_buf, *recv_buf;

-    pj_ioqueue_t *ioque = NULL;

-    pj_ioqueue_key_t *skey, *ckey, *key;

-    pj_timestamp t1, t2, t_elapsed;

-    int rc=0, i;

-    pj_str_t temp;

-    char errbuf[128];

-

-    // Create pool.

-    pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);

-

-    // Allocate buffers for send and receive.

-    send_buf = (char*)pj_pool_alloc(pool, bufsize);

-    recv_buf = (char*)pj_pool_alloc(pool, bufsize);

-

-    // Allocate sockets for sending and receiving.

-    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &ssock);

-    if (rc == PJ_SUCCESS) {

-        rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &csock);

-    } else

-        csock = PJ_INVALID_SOCKET;

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: pj_sock_socket()", rc);

-	goto on_error;

-    }

-

-    // Bind server socket.

-    memset(&addr, 0, sizeof(addr));

-    addr.sin_family = PJ_AF_INET;

-    addr.sin_port = pj_htons(PORT);

-    if (pj_sock_bind(ssock, &addr, sizeof(addr)))

-	goto on_error;

-

-    pj_assert(inactive_sock_count+2 <= PJ_IOQUEUE_MAX_HANDLES);

-

-    // Create I/O Queue.

-    rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: pj_ioqueue_create()", rc);

-	goto on_error;

-    }

-

-    // Allocate inactive sockets, and bind them to some arbitrary address.

-    // Then register them to the I/O queue, and start a read operation.

-    inactive_sock = (pj_sock_t*)pj_pool_alloc(pool, 

-				    inactive_sock_count*sizeof(pj_sock_t));

-    inactive_read_op = (pj_ioqueue_op_key_t*)pj_pool_alloc(pool,

-                              inactive_sock_count*sizeof(pj_ioqueue_op_key_t));

-    memset(&addr, 0, sizeof(addr));

-    addr.sin_family = PJ_AF_INET;

-    for (i=0; i<inactive_sock_count; ++i) {

-        pj_ssize_t bytes;

-

-	rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &inactive_sock[i]);

-	if (rc != PJ_SUCCESS || inactive_sock[i] < 0) {

-	    app_perror("...error: pj_sock_socket()", rc);

-	    goto on_error;

-	}

-	if ((rc=pj_sock_bind(inactive_sock[i], &addr, sizeof(addr))) != 0) {

-	    pj_sock_close(inactive_sock[i]);

-	    inactive_sock[i] = PJ_INVALID_SOCKET;

-	    app_perror("...error: pj_sock_bind()", rc);

-	    goto on_error;

-	}

-	rc = pj_ioqueue_register_sock(pool, ioque, inactive_sock[i], 

-			              NULL, &test_cb, &key);

-	if (rc != PJ_SUCCESS) {

-	    pj_sock_close(inactive_sock[i]);

-	    inactive_sock[i] = PJ_INVALID_SOCKET;

-	    app_perror("...error(1): pj_ioqueue_register_sock()", rc);

-	    PJ_LOG(3,(THIS_FILE, "....i=%d", i));

-	    goto on_error;

-	}

-        bytes = bufsize;

-	rc = pj_ioqueue_recv(key, &inactive_read_op[i], recv_buf, &bytes, 0);

-	if ( rc < 0 && rc != PJ_EPENDING) {

-	    pj_sock_close(inactive_sock[i]);

-	    inactive_sock[i] = PJ_INVALID_SOCKET;

-	    app_perror("...error: pj_ioqueue_read()", rc);

-	    goto on_error;

-	}

-    }

-

-    // Register server and client socket.

-    // We put this after inactivity socket, hopefully this can represent the

-    // worst waiting time.

-    rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL, 

-			          &test_cb, &skey);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error(2): pj_ioqueue_register_sock()", rc);

-	goto on_error;

-    }

-

-    rc = pj_ioqueue_register_sock(pool, ioque, csock, NULL, 

-			          &test_cb, &ckey);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error(3): pj_ioqueue_register_sock()", rc);

-	goto on_error;

-    }

-

-    // Set destination address to send the packet.

-    pj_sockaddr_in_init(&addr, pj_cstr(&temp, "127.0.0.1"), PORT);

-

-    // Test loop.

-    t_elapsed.u64 = 0;

-    for (i=0; i<LOOP; ++i) {

-	pj_ssize_t bytes;

-        pj_ioqueue_op_key_t read_op, write_op;

-

-	// Randomize send buffer.

-	pj_create_random_string(send_buf, bufsize);

-

-	// Start reading on the server side.

-        bytes = bufsize;

-	rc = pj_ioqueue_recv(skey, &read_op, recv_buf, &bytes, 0);

-	if (rc < 0 && rc != PJ_EPENDING) {

-	    app_perror("...error: pj_ioqueue_read()", rc);

-	    break;

-	}

-

-	// Starts send on the client side.

-        bytes = bufsize;

-	rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0,

-			       &addr, sizeof(addr));

-	if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {

-	    app_perror("...error: pj_ioqueue_write()", bytes);

-	    rc = -1;

-	    break;

-	}

-

-	// Begin time.

-	pj_get_timestamp(&t1);

-

-	// Poll the queue until we've got completion event in the server side.

-        callback_read_key = NULL;

-        callback_read_size = 0;

-	do {

-	    rc = pj_ioqueue_poll(ioque, NULL);

-	} while (rc >= 0 && callback_read_key != skey);

-

-	// End time.

-	pj_get_timestamp(&t2);

-	t_elapsed.u64 += (t2.u64 - t1.u64);

-

-	if (rc < 0)

-	    break;

-

-	// Compare recv buffer with send buffer.

-	if (callback_read_size != bufsize || 

-	    memcmp(send_buf, recv_buf, bufsize)) 

-	{

-	    rc = -1;

-	    break;

-	}

-

-	// Poll until all events are exhausted, before we start the next loop.

-	do {

-	    pj_time_val timeout = { 0, 10 };

-	    rc = pj_ioqueue_poll(ioque, &timeout);

-	} while (rc>0);

-

-	rc = 0;

-    }

-

-    // Print results

-    if (rc == 0) {

-	pj_timestamp tzero;

-	pj_uint32_t usec_delay;

-

-	tzero.u32.hi = tzero.u32.lo = 0;

-	usec_delay = pj_elapsed_usec( &tzero, &t_elapsed);

-

-	PJ_LOG(3, (THIS_FILE, "...%10d %15d  % 9d", 

-	           bufsize, inactive_sock_count, usec_delay));

-

-    } else {

-	PJ_LOG(2, (THIS_FILE, "...ERROR (buf:%d, fds:%d)", 

-			      bufsize, inactive_sock_count+2));

-    }

-

-    // Cleaning up.

-    for (i=0; i<inactive_sock_count; ++i)

-	pj_sock_close(inactive_sock[i]);

-    pj_sock_close(ssock);

-    pj_sock_close(csock);

-

-    pj_ioqueue_destroy(ioque);

-    pj_pool_release( pool);

-    return 0;

-

-on_error:

-    PJ_LOG(1,(THIS_FILE, "...ERROR: %s", 

-	      pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf))));

-    if (ssock)

-	pj_sock_close(ssock);

-    if (csock)

-	pj_sock_close(csock);

-    for (i=0; i<inactive_sock_count && inactive_sock && 

-	      inactive_sock[i]!=PJ_INVALID_SOCKET; ++i) 

-    {

-	pj_sock_close(inactive_sock[i]);

-    }

-    if (ioque != NULL)

-	pj_ioqueue_destroy(ioque);

-    pj_pool_release( pool);

-    return -1;

-}

-

-int udp_ioqueue_test()

-{

-    int status;

-    int bufsize, sock_count;

-

-    PJ_LOG(3, (THIS_FILE, "...compliance test (%s)", pj_ioqueue_name()));

-    if ((status=compliance_test()) != 0) {

-	return status;

-    }

-    PJ_LOG(3, (THIS_FILE, "....compliance test ok"));

-

-    if ((status=many_handles_test()) != 0) {

-	return status;

-    }

-    

-    PJ_LOG(4, (THIS_FILE, "...benchmarking different buffer size:"));

-    PJ_LOG(4, (THIS_FILE, "... note: buf=bytes sent, fds=# of fds, "

-			  "elapsed=in timer ticks"));

-

-    PJ_LOG(3, (THIS_FILE, "...Benchmarking poll times for %s:", pj_ioqueue_name()));

-    PJ_LOG(3, (THIS_FILE, "...====================================="));

-    PJ_LOG(3, (THIS_FILE, "...Buf.size   #inactive-socks  Time/poll"));

-    PJ_LOG(3, (THIS_FILE, "... (bytes)                    (nanosec)"));

-    PJ_LOG(3, (THIS_FILE, "...====================================="));

-

-    for (bufsize=BUF_MIN_SIZE; bufsize <= BUF_MAX_SIZE; bufsize *= 2) {

-	if (bench_test(bufsize, SOCK_INACTIVE_MIN))

-	    return -1;

-    }

-    bufsize = 512;

-    for (sock_count=SOCK_INACTIVE_MIN+2; 

-	 sock_count<=SOCK_INACTIVE_MAX+2; 

-	 sock_count *= 2) 

-    {

-	//PJ_LOG(3,(THIS_FILE, "...testing with %d fds", sock_count));

-	if (bench_test(bufsize, sock_count-2))

-	    return -1;

-    }

-    return 0;

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_uiq_udp;

-#endif	/* INCLUDE_UDP_IOQUEUE_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+
+/**
+ * \page page_pjlib_ioqueue_udp_test Test: I/O Queue (UDP)
+ *
+ * This file provides implementation to test the
+ * functionality of the I/O queue when UDP socket is used.
+ *
+ *
+ * This file is <b>pjlib-test/ioq_udp.c</b>
+ *
+ * \include pjlib-test/ioq_udp.c
+ */
+
+
+#if INCLUDE_UDP_IOQUEUE_TEST
+
+#include <pjlib.h>
+
+#include <pj/compat/socket.h>
+
+#define THIS_FILE	    "test_udp"
+#define PORT		    51233
+#define LOOP		    100
+#define BUF_MIN_SIZE	    32
+#define BUF_MAX_SIZE	    2048
+#define SOCK_INACTIVE_MIN   (1)
+#define SOCK_INACTIVE_MAX   (PJ_IOQUEUE_MAX_HANDLES - 2)
+#define POOL_SIZE	    (2*BUF_MAX_SIZE + SOCK_INACTIVE_MAX*128 + 2048)
+
+#undef TRACE_
+#define TRACE_(msg)	    PJ_LOG(3,(THIS_FILE,"....." msg))
+
+static pj_ssize_t            callback_read_size,
+                             callback_write_size,
+                             callback_accept_status,
+                             callback_connect_status;
+static pj_ioqueue_key_t     *callback_read_key,
+                            *callback_write_key,
+                            *callback_accept_key,
+                            *callback_connect_key;
+static pj_ioqueue_op_key_t  *callback_read_op,
+                            *callback_write_op,
+                            *callback_accept_op;
+
+static void on_ioqueue_read(pj_ioqueue_key_t *key, 
+                            pj_ioqueue_op_key_t *op_key,
+                            pj_ssize_t bytes_read)
+{
+    callback_read_key = key;
+    callback_read_op = op_key;
+    callback_read_size = bytes_read;
+}
+
+static void on_ioqueue_write(pj_ioqueue_key_t *key, 
+                             pj_ioqueue_op_key_t *op_key,
+                             pj_ssize_t bytes_written)
+{
+    callback_write_key = key;
+    callback_write_op = op_key;
+    callback_write_size = bytes_written;
+}
+
+static void on_ioqueue_accept(pj_ioqueue_key_t *key, 
+                              pj_ioqueue_op_key_t *op_key,
+                              pj_sock_t sock, int status)
+{
+    PJ_UNUSED_ARG(sock);
+    callback_accept_key = key;
+    callback_accept_op = op_key;
+    callback_accept_status = status;
+}
+
+static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status)
+{
+    callback_connect_key = key;
+    callback_connect_status = status;
+}
+
+static pj_ioqueue_callback test_cb = 
+{
+    &on_ioqueue_read,
+    &on_ioqueue_write,
+    &on_ioqueue_accept,
+    &on_ioqueue_connect,
+};
+
+#ifdef PJ_WIN32
+#  define S_ADDR S_un.S_addr
+#else
+#  define S_ADDR s_addr
+#endif
+
+/*
+ * compliance_test()
+ * To test that the basic IOQueue functionality works. It will just exchange
+ * data between two sockets.
+ */ 
+static int compliance_test(void)
+{
+    pj_sock_t ssock=-1, csock=-1;
+    pj_sockaddr_in addr;
+    int addrlen;
+    pj_pool_t *pool = NULL;
+    char *send_buf, *recv_buf;
+    pj_ioqueue_t *ioque = NULL;
+    pj_ioqueue_key_t *skey, *ckey;
+    pj_ioqueue_op_key_t read_op, write_op;
+    int bufsize = BUF_MIN_SIZE;
+    pj_ssize_t bytes, status = -1;
+    pj_str_t temp;
+    pj_bool_t send_pending, recv_pending;
+    pj_status_t rc;
+
+    pj_set_os_error(PJ_SUCCESS);
+
+    // Create pool.
+    pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);
+
+    // Allocate buffers for send and receive.
+    send_buf = (char*)pj_pool_alloc(pool, bufsize);
+    recv_buf = (char*)pj_pool_alloc(pool, bufsize);
+
+    // Allocate sockets for sending and receiving.
+    TRACE_("creating sockets...");
+    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &ssock);
+    if (rc==PJ_SUCCESS)
+        rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &csock);
+    else
+        csock = PJ_INVALID_SOCKET;
+    if (rc != PJ_SUCCESS) {
+        app_perror("...ERROR in pj_sock_socket()", rc);
+	status=-1; goto on_error;
+    }
+
+    // Bind server socket.
+    TRACE_("bind socket...");
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = PJ_AF_INET;
+    addr.sin_port = pj_htons(PORT);
+    if (pj_sock_bind(ssock, &addr, sizeof(addr))) {
+	status=-10; goto on_error;
+    }
+
+    // Create I/O Queue.
+    TRACE_("create ioqueue...");
+    rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);
+    if (rc != PJ_SUCCESS) {
+	status=-20; goto on_error;
+    }
+
+    // Register server and client socket.
+    // We put this after inactivity socket, hopefully this can represent the
+    // worst waiting time.
+    TRACE_("registering first sockets...");
+    rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL, 
+			          &test_cb, &skey);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error(10): ioqueue_register error", rc);
+	status=-25; goto on_error;
+    }
+    TRACE_("registering second sockets...");
+    rc = pj_ioqueue_register_sock( pool, ioque, csock, NULL, 
+			           &test_cb, &ckey);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error(11): ioqueue_register error", rc);
+	status=-26; goto on_error;
+    }
+
+    // Set destination address to send the packet.
+    TRACE_("set destination address...");
+    temp = pj_str("127.0.0.1");
+    if ((rc=pj_sockaddr_in_init(&addr, &temp, PORT)) != 0) {
+	app_perror("...error: unable to resolve 127.0.0.1", rc);
+	status=-26; goto on_error;
+    }
+
+    // Randomize send_buf.
+    pj_create_random_string(send_buf, bufsize);
+
+    // Register reading from ioqueue.
+    TRACE_("start recvfrom...");
+    addrlen = sizeof(addr);
+    bytes = bufsize;
+    rc = pj_ioqueue_recvfrom(skey, &read_op, recv_buf, &bytes, 0,
+			     &addr, &addrlen);
+    if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
+        app_perror("...error: pj_ioqueue_recvfrom", rc);
+	status=-28; goto on_error;
+    } else if (rc == PJ_EPENDING) {
+	recv_pending = 1;
+	PJ_LOG(3, (THIS_FILE, 
+		   "......ok: recvfrom returned pending"));
+    } else {
+	PJ_LOG(3, (THIS_FILE, 
+		   "......error: recvfrom returned immediate ok!"));
+	status=-29; goto on_error;
+    }
+
+    // Write must return the number of bytes.
+    TRACE_("start sendto...");
+    bytes = bufsize;
+    rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0, &addr, 
+			   sizeof(addr));
+    if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
+        app_perror("...error: pj_ioqueue_sendto", rc);
+	status=-30; goto on_error;
+    } else if (rc == PJ_EPENDING) {
+	send_pending = 1;
+	PJ_LOG(3, (THIS_FILE, 
+		   "......ok: sendto returned pending"));
+    } else {
+	send_pending = 0;
+	PJ_LOG(3, (THIS_FILE, 
+		   "......ok: sendto returned immediate success"));
+    }
+
+    // reset callback variables.
+    callback_read_size = callback_write_size = 0;
+    callback_accept_status = callback_connect_status = -2;
+    callback_read_key = callback_write_key = 
+        callback_accept_key = callback_connect_key = NULL;
+    callback_read_op = callback_write_op = NULL;
+
+    // Poll if pending.
+    while (send_pending || recv_pending) {
+	int rc;
+	pj_time_val timeout = { 5, 0 };
+
+	TRACE_("poll...");
+	rc = pj_ioqueue_poll(ioque, &timeout);
+
+	if (rc == 0) {
+	    PJ_LOG(1,(THIS_FILE, "...ERROR: timed out..."));
+	    status=-45; goto on_error;
+        } else if (rc < 0) {
+            app_perror("...ERROR in ioqueue_poll()", rc);
+	    status=-50; goto on_error;
+	}
+
+	if (callback_read_key != NULL) {
+            if (callback_read_size != bufsize) {
+                status=-61; goto on_error;
+            }
+            if (callback_read_key != skey) {
+                status=-65; goto on_error;
+            }
+            if (callback_read_op != &read_op) {
+                status=-66; goto on_error;
+            }
+
+	    if (memcmp(send_buf, recv_buf, bufsize) != 0) {
+		status=-70; goto on_error;
+	    }
+
+
+	    recv_pending = 0;
+	} 
+
+        if (callback_write_key != NULL) {
+            if (callback_write_size != bufsize) {
+                status=-73; goto on_error;
+            }
+            if (callback_write_key != ckey) {
+                status=-75; goto on_error;
+            }
+            if (callback_write_op != &write_op) {
+                status=-76; goto on_error;
+            }
+
+            send_pending = 0;
+	}
+    } 
+    
+    // Success
+    status = 0;
+
+on_error:
+    if (status != 0) {
+	char errbuf[128];
+	PJ_LOG(1, (THIS_FILE, 
+		   "...compliance test error: status=%d, os_err=%d (%s)", 
+		   status, pj_get_netos_error(),
+	           pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf))));
+    }
+    if (ssock)
+	pj_sock_close(ssock);
+    if (csock)
+	pj_sock_close(csock);
+    if (ioque != NULL)
+	pj_ioqueue_destroy(ioque);
+    pj_pool_release(pool);
+    return status;
+
+}
+
+/*
+ * Testing with many handles.
+ * This will just test registering PJ_IOQUEUE_MAX_HANDLES count
+ * of sockets to the ioqueue.
+ */
+static int many_handles_test(void)
+{
+    enum { MAX = PJ_IOQUEUE_MAX_HANDLES };
+    pj_pool_t *pool;
+    pj_ioqueue_t *ioqueue;
+    pj_sock_t *sock;
+    pj_ioqueue_key_t **key;
+    pj_status_t rc;
+    int count, i;
+
+    PJ_LOG(3,(THIS_FILE,"...testing with so many handles"));
+
+    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
+    if (!pool)
+	return PJ_ENOMEM;
+
+    key = pj_pool_alloc(pool, MAX*sizeof(pj_ioqueue_key_t*));
+    sock = pj_pool_alloc(pool, MAX*sizeof(pj_sock_t));
+    
+    /* Create IOQueue */
+    rc = pj_ioqueue_create(pool, MAX, &ioqueue);
+    if (rc != PJ_SUCCESS || ioqueue == NULL) {
+	app_perror("...error in pj_ioqueue_create", rc);
+	return -10;
+    }
+
+    /* Register as many sockets. */
+    for (count=0; count<MAX; ++count) {
+	sock[count] = PJ_INVALID_SOCKET;
+	rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[count]);
+	if (rc != PJ_SUCCESS || sock[count] == PJ_INVALID_SOCKET) {
+	    PJ_LOG(3,(THIS_FILE, "....unable to create %d-th socket, rc=%d", 
+				 count, rc));
+	    break;
+	}
+	key[count] = NULL;
+	rc = pj_ioqueue_register_sock(pool, ioqueue, sock[count],
+				      NULL, &test_cb, &key[count]);
+	if (rc != PJ_SUCCESS || key[count] == NULL) {
+	    PJ_LOG(3,(THIS_FILE, "....unable to register %d-th socket, rc=%d", 
+				 count, rc));
+	    return -30;
+	}
+    }
+
+    /* Test complete. */
+
+    /* Now deregister and close all handles. */ 
+
+    for (i=0; i<count; ++i) {
+	rc = pj_ioqueue_unregister(key[i]);
+	if (rc != PJ_SUCCESS) {
+	    app_perror("...error in pj_ioqueue_unregister", rc);
+	}
+	rc = pj_sock_close(sock[i]);
+	if (rc != PJ_SUCCESS) {
+	    app_perror("...error in pj_sock_close", rc);
+	}
+    }
+
+    rc = pj_ioqueue_destroy(ioqueue);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error in pj_ioqueue_destroy", rc);
+    }
+    
+    pj_pool_release(pool);
+
+    PJ_LOG(3,(THIS_FILE,"....many_handles_test() ok"));
+
+    return 0;
+}
+
+/*
+ * Multi-operation test.
+ */
+
+/*
+ * Benchmarking IOQueue
+ */
+static int bench_test(int bufsize, int inactive_sock_count)
+{
+    pj_sock_t ssock=-1, csock=-1;
+    pj_sockaddr_in addr;
+    pj_pool_t *pool = NULL;
+    pj_sock_t *inactive_sock=NULL;
+    pj_ioqueue_op_key_t *inactive_read_op;
+    char *send_buf, *recv_buf;
+    pj_ioqueue_t *ioque = NULL;
+    pj_ioqueue_key_t *skey, *ckey, *key;
+    pj_timestamp t1, t2, t_elapsed;
+    int rc=0, i;
+    pj_str_t temp;
+    char errbuf[128];
+
+    // Create pool.
+    pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);
+
+    // Allocate buffers for send and receive.
+    send_buf = (char*)pj_pool_alloc(pool, bufsize);
+    recv_buf = (char*)pj_pool_alloc(pool, bufsize);
+
+    // Allocate sockets for sending and receiving.
+    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &ssock);
+    if (rc == PJ_SUCCESS) {
+        rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &csock);
+    } else
+        csock = PJ_INVALID_SOCKET;
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: pj_sock_socket()", rc);
+	goto on_error;
+    }
+
+    // Bind server socket.
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = PJ_AF_INET;
+    addr.sin_port = pj_htons(PORT);
+    if (pj_sock_bind(ssock, &addr, sizeof(addr)))
+	goto on_error;
+
+    pj_assert(inactive_sock_count+2 <= PJ_IOQUEUE_MAX_HANDLES);
+
+    // Create I/O Queue.
+    rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: pj_ioqueue_create()", rc);
+	goto on_error;
+    }
+
+    // Allocate inactive sockets, and bind them to some arbitrary address.
+    // Then register them to the I/O queue, and start a read operation.
+    inactive_sock = (pj_sock_t*)pj_pool_alloc(pool, 
+				    inactive_sock_count*sizeof(pj_sock_t));
+    inactive_read_op = (pj_ioqueue_op_key_t*)pj_pool_alloc(pool,
+                              inactive_sock_count*sizeof(pj_ioqueue_op_key_t));
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = PJ_AF_INET;
+    for (i=0; i<inactive_sock_count; ++i) {
+        pj_ssize_t bytes;
+
+	rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &inactive_sock[i]);
+	if (rc != PJ_SUCCESS || inactive_sock[i] < 0) {
+	    app_perror("...error: pj_sock_socket()", rc);
+	    goto on_error;
+	}
+	if ((rc=pj_sock_bind(inactive_sock[i], &addr, sizeof(addr))) != 0) {
+	    pj_sock_close(inactive_sock[i]);
+	    inactive_sock[i] = PJ_INVALID_SOCKET;
+	    app_perror("...error: pj_sock_bind()", rc);
+	    goto on_error;
+	}
+	rc = pj_ioqueue_register_sock(pool, ioque, inactive_sock[i], 
+			              NULL, &test_cb, &key);
+	if (rc != PJ_SUCCESS) {
+	    pj_sock_close(inactive_sock[i]);
+	    inactive_sock[i] = PJ_INVALID_SOCKET;
+	    app_perror("...error(1): pj_ioqueue_register_sock()", rc);
+	    PJ_LOG(3,(THIS_FILE, "....i=%d", i));
+	    goto on_error;
+	}
+        bytes = bufsize;
+	rc = pj_ioqueue_recv(key, &inactive_read_op[i], recv_buf, &bytes, 0);
+	if ( rc < 0 && rc != PJ_EPENDING) {
+	    pj_sock_close(inactive_sock[i]);
+	    inactive_sock[i] = PJ_INVALID_SOCKET;
+	    app_perror("...error: pj_ioqueue_read()", rc);
+	    goto on_error;
+	}
+    }
+
+    // Register server and client socket.
+    // We put this after inactivity socket, hopefully this can represent the
+    // worst waiting time.
+    rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL, 
+			          &test_cb, &skey);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error(2): pj_ioqueue_register_sock()", rc);
+	goto on_error;
+    }
+
+    rc = pj_ioqueue_register_sock(pool, ioque, csock, NULL, 
+			          &test_cb, &ckey);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error(3): pj_ioqueue_register_sock()", rc);
+	goto on_error;
+    }
+
+    // Set destination address to send the packet.
+    pj_sockaddr_in_init(&addr, pj_cstr(&temp, "127.0.0.1"), PORT);
+
+    // Test loop.
+    t_elapsed.u64 = 0;
+    for (i=0; i<LOOP; ++i) {
+	pj_ssize_t bytes;
+        pj_ioqueue_op_key_t read_op, write_op;
+
+	// Randomize send buffer.
+	pj_create_random_string(send_buf, bufsize);
+
+	// Start reading on the server side.
+        bytes = bufsize;
+	rc = pj_ioqueue_recv(skey, &read_op, recv_buf, &bytes, 0);
+	if (rc < 0 && rc != PJ_EPENDING) {
+	    app_perror("...error: pj_ioqueue_read()", rc);
+	    break;
+	}
+
+	// Starts send on the client side.
+        bytes = bufsize;
+	rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0,
+			       &addr, sizeof(addr));
+	if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
+	    app_perror("...error: pj_ioqueue_write()", bytes);
+	    rc = -1;
+	    break;
+	}
+
+	// Begin time.
+	pj_get_timestamp(&t1);
+
+	// Poll the queue until we've got completion event in the server side.
+        callback_read_key = NULL;
+        callback_read_size = 0;
+	do {
+	    rc = pj_ioqueue_poll(ioque, NULL);
+	} while (rc >= 0 && callback_read_key != skey);
+
+	// End time.
+	pj_get_timestamp(&t2);
+	t_elapsed.u64 += (t2.u64 - t1.u64);
+
+	if (rc < 0)
+	    break;
+
+	// Compare recv buffer with send buffer.
+	if (callback_read_size != bufsize || 
+	    memcmp(send_buf, recv_buf, bufsize)) 
+	{
+	    rc = -1;
+	    break;
+	}
+
+	// Poll until all events are exhausted, before we start the next loop.
+	do {
+	    pj_time_val timeout = { 0, 10 };
+	    rc = pj_ioqueue_poll(ioque, &timeout);
+	} while (rc>0);
+
+	rc = 0;
+    }
+
+    // Print results
+    if (rc == 0) {
+	pj_timestamp tzero;
+	pj_uint32_t usec_delay;
+
+	tzero.u32.hi = tzero.u32.lo = 0;
+	usec_delay = pj_elapsed_usec( &tzero, &t_elapsed);
+
+	PJ_LOG(3, (THIS_FILE, "...%10d %15d  % 9d", 
+	           bufsize, inactive_sock_count, usec_delay));
+
+    } else {
+	PJ_LOG(2, (THIS_FILE, "...ERROR (buf:%d, fds:%d)", 
+			      bufsize, inactive_sock_count+2));
+    }
+
+    // Cleaning up.
+    for (i=0; i<inactive_sock_count; ++i)
+	pj_sock_close(inactive_sock[i]);
+    pj_sock_close(ssock);
+    pj_sock_close(csock);
+
+    pj_ioqueue_destroy(ioque);
+    pj_pool_release( pool);
+    return 0;
+
+on_error:
+    PJ_LOG(1,(THIS_FILE, "...ERROR: %s", 
+	      pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf))));
+    if (ssock)
+	pj_sock_close(ssock);
+    if (csock)
+	pj_sock_close(csock);
+    for (i=0; i<inactive_sock_count && inactive_sock && 
+	      inactive_sock[i]!=PJ_INVALID_SOCKET; ++i) 
+    {
+	pj_sock_close(inactive_sock[i]);
+    }
+    if (ioque != NULL)
+	pj_ioqueue_destroy(ioque);
+    pj_pool_release( pool);
+    return -1;
+}
+
+int udp_ioqueue_test()
+{
+    int status;
+    int bufsize, sock_count;
+
+    PJ_LOG(3, (THIS_FILE, "...compliance test (%s)", pj_ioqueue_name()));
+    if ((status=compliance_test()) != 0) {
+	return status;
+    }
+    PJ_LOG(3, (THIS_FILE, "....compliance test ok"));
+
+    if ((status=many_handles_test()) != 0) {
+	return status;
+    }
+    
+    PJ_LOG(4, (THIS_FILE, "...benchmarking different buffer size:"));
+    PJ_LOG(4, (THIS_FILE, "... note: buf=bytes sent, fds=# of fds, "
+			  "elapsed=in timer ticks"));
+
+    PJ_LOG(3, (THIS_FILE, "...Benchmarking poll times for %s:", pj_ioqueue_name()));
+    PJ_LOG(3, (THIS_FILE, "...====================================="));
+    PJ_LOG(3, (THIS_FILE, "...Buf.size   #inactive-socks  Time/poll"));
+    PJ_LOG(3, (THIS_FILE, "... (bytes)                    (nanosec)"));
+    PJ_LOG(3, (THIS_FILE, "...====================================="));
+
+    for (bufsize=BUF_MIN_SIZE; bufsize <= BUF_MAX_SIZE; bufsize *= 2) {
+	if (bench_test(bufsize, SOCK_INACTIVE_MIN))
+	    return -1;
+    }
+    bufsize = 512;
+    for (sock_count=SOCK_INACTIVE_MIN+2; 
+	 sock_count<=SOCK_INACTIVE_MAX+2; 
+	 sock_count *= 2) 
+    {
+	//PJ_LOG(3,(THIS_FILE, "...testing with %d fds", sock_count));
+	if (bench_test(bufsize, sock_count-2))
+	    return -1;
+    }
+    return 0;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_uiq_udp;
+#endif	/* INCLUDE_UDP_IOQUEUE_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/list.c b/pjlib/src/pjlib-test/list.c
index 4777a9f..7aa638b 100644
--- a/pjlib/src/pjlib-test/list.c
+++ b/pjlib/src/pjlib-test/list.c
@@ -1,225 +1,225 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-/**

- * \page page_pjlib_list_test Test: Linked List

- *

- * This file provides implementation of \b list_test(). It tests the

- * functionality of the linked-list API.

- *

- * \section list_test_sec Scope of the Test

- *

- * API tested:

- *  - pj_list_init()

- *  - pj_list_insert_before()

- *  - pj_list_insert_after()

- *  - pj_list_merge_last()

- *  - pj_list_empty()

- *  - pj_list_insert_nodes_before()

- *  - pj_list_erase()

- *  - pj_list_find_node()

- *  - pj_list_search()

- *

- *

- * This file is <b>pjlib-test/list.c</b>

- *

- * \include pjlib-test/list.c

- */

-

-#if INCLUDE_LIST_TEST

-

-#include <pjlib.h>

-

-typedef struct list_node

-{

-    PJ_DECL_LIST_MEMBER(struct list_node);

-    int value;

-} list_node;

-

-static int compare_node(void *value, const pj_list_type *nd)

-{

-    list_node *node = (list_node*)nd;

-    return ((long)value == node->value) ? 0 : -1;

-}

-

-#define PJ_SIGNED_ARRAY_SIZE(a)	((int)PJ_ARRAY_SIZE(a))

-

-int list_test()

-{

-    list_node nodes[4];    // must be even number of nodes

-    list_node list;

-    list_node list2;

-    list_node *p;

-    int i; // don't change to unsigned!

-

-    //

-    // Test insert_before().

-    //

-    list.value = (unsigned)-1;

-    pj_list_init(&list);

-    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {

-	nodes[i].value = i;

-	pj_list_insert_before(&list, &nodes[i]);

-    }

-    // check.

-    for (i=0, p=list.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {

-	pj_assert(p->value == i);

-	if (p->value != i) {

-	    return -1;

-	}

-    }

-

-    //

-    // Test insert_after()

-    //

-    pj_list_init(&list);

-    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)-1; i>=0; --i) {

-	pj_list_insert_after(&list, &nodes[i]);

-    }

-    // check.

-    for (i=0, p=list.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {

-	pj_assert(p->value == i);

-	if (p->value != i) {

-	    return -1;

-	}

-    }

-

-    //

-    // Test merge_last()

-    //

-    // Init lists

-    pj_list_init(&list);

-    pj_list_init(&list2);

-    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes)/2; ++i) {

-	pj_list_insert_before(&list, &nodes[i]);

-    }

-    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)/2; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {

-	pj_list_insert_before(&list2, &nodes[i]);

-    }

-    // merge

-    pj_list_merge_last(&list, &list2);

-    // check.

-    for (i=0, p=list.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {

-	pj_assert(p->value == i);

-	if (p->value != i) {

-	    return -1;

-	}

-    }

-    // check list is empty

-    pj_assert( pj_list_empty(&list2) );

-    if (!pj_list_empty(&list2)) {

-	return -1;

-    }

-

-    // 

-    // Check merge_first()

-    //

-    pj_list_init(&list);

-    pj_list_init(&list2);

-    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes)/2; ++i) {

-	pj_list_insert_before(&list, &nodes[i]);

-    }

-    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)/2; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {

-	pj_list_insert_before(&list2, &nodes[i]);

-    }

-    // merge

-    pj_list_merge_first(&list2, &list);

-    // check (list2).

-    for (i=0, p=list2.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {

-	pj_assert(p->value == i);

-	if (p->value != i) {

-	    return -1;

-	}

-    }

-    // check list is empty

-    pj_assert( pj_list_empty(&list) );

-    if (!pj_list_empty(&list)) {

-	return -1;

-    }

-

-    //

-    // Test insert_nodes_before()

-    //

-    // init list

-    pj_list_init(&list);

-    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes)/2; ++i) {

-	pj_list_insert_before(&list, &nodes[i]);

-    }

-    // chain remaining nodes

-    pj_list_init(&nodes[PJ_SIGNED_ARRAY_SIZE(nodes)/2]);

-    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)/2+1; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {

-	pj_list_insert_before(&nodes[PJ_SIGNED_ARRAY_SIZE(nodes)/2], &nodes[i]);

-    }

-    // insert nodes

-    pj_list_insert_nodes_before(&list, &nodes[PJ_SIGNED_ARRAY_SIZE(nodes)/2]);

-    // check

-    for (i=0, p=list.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {

-	pj_assert(p->value == i);

-	if (p->value != i) {

-	    return -1;

-	}

-    }

-

-    // erase test.

-    pj_list_init(&list);

-    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {

-	nodes[i].value = i;

-	pj_list_insert_before(&list, &nodes[i]);

-    }

-    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)-1; i>=0; --i) {

-	int j;

-	pj_list_erase(&nodes[i]);

-	for (j=0, p=list.next; j<i; ++j, p=p->next) {

-	    pj_assert(p->value == j);

-	    if (p->value != j) {

-		return -1;

-	    }

-	}

-    }

-

-    // find and search

-    pj_list_init(&list);

-    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {

-	nodes[i].value = i;

-	pj_list_insert_before(&list, &nodes[i]);

-    }

-    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {

-	p = (list_node*) pj_list_find_node(&list, &nodes[i]);

-	pj_assert( p == &nodes[i] );

-	if (p != &nodes[i]) {

-	    return -1;

-	}

-	p = (list_node*) pj_list_search(&list, (void*)(long)i, &compare_node);

-	pj_assert( p == &nodes[i] );

-	if (p != &nodes[i]) {

-	    return -1;

-	}

-    }

-    return 0;

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_list_test;

-#endif	/* INCLUDE_LIST_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+/**
+ * \page page_pjlib_list_test Test: Linked List
+ *
+ * This file provides implementation of \b list_test(). It tests the
+ * functionality of the linked-list API.
+ *
+ * \section list_test_sec Scope of the Test
+ *
+ * API tested:
+ *  - pj_list_init()
+ *  - pj_list_insert_before()
+ *  - pj_list_insert_after()
+ *  - pj_list_merge_last()
+ *  - pj_list_empty()
+ *  - pj_list_insert_nodes_before()
+ *  - pj_list_erase()
+ *  - pj_list_find_node()
+ *  - pj_list_search()
+ *
+ *
+ * This file is <b>pjlib-test/list.c</b>
+ *
+ * \include pjlib-test/list.c
+ */
+
+#if INCLUDE_LIST_TEST
+
+#include <pjlib.h>
+
+typedef struct list_node
+{
+    PJ_DECL_LIST_MEMBER(struct list_node);
+    int value;
+} list_node;
+
+static int compare_node(void *value, const pj_list_type *nd)
+{
+    list_node *node = (list_node*)nd;
+    return ((long)value == node->value) ? 0 : -1;
+}
+
+#define PJ_SIGNED_ARRAY_SIZE(a)	((int)PJ_ARRAY_SIZE(a))
+
+int list_test()
+{
+    list_node nodes[4];    // must be even number of nodes
+    list_node list;
+    list_node list2;
+    list_node *p;
+    int i; // don't change to unsigned!
+
+    //
+    // Test insert_before().
+    //
+    list.value = (unsigned)-1;
+    pj_list_init(&list);
+    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {
+	nodes[i].value = i;
+	pj_list_insert_before(&list, &nodes[i]);
+    }
+    // check.
+    for (i=0, p=list.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {
+	pj_assert(p->value == i);
+	if (p->value != i) {
+	    return -1;
+	}
+    }
+
+    //
+    // Test insert_after()
+    //
+    pj_list_init(&list);
+    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)-1; i>=0; --i) {
+	pj_list_insert_after(&list, &nodes[i]);
+    }
+    // check.
+    for (i=0, p=list.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {
+	pj_assert(p->value == i);
+	if (p->value != i) {
+	    return -1;
+	}
+    }
+
+    //
+    // Test merge_last()
+    //
+    // Init lists
+    pj_list_init(&list);
+    pj_list_init(&list2);
+    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes)/2; ++i) {
+	pj_list_insert_before(&list, &nodes[i]);
+    }
+    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)/2; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {
+	pj_list_insert_before(&list2, &nodes[i]);
+    }
+    // merge
+    pj_list_merge_last(&list, &list2);
+    // check.
+    for (i=0, p=list.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {
+	pj_assert(p->value == i);
+	if (p->value != i) {
+	    return -1;
+	}
+    }
+    // check list is empty
+    pj_assert( pj_list_empty(&list2) );
+    if (!pj_list_empty(&list2)) {
+	return -1;
+    }
+
+    // 
+    // Check merge_first()
+    //
+    pj_list_init(&list);
+    pj_list_init(&list2);
+    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes)/2; ++i) {
+	pj_list_insert_before(&list, &nodes[i]);
+    }
+    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)/2; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {
+	pj_list_insert_before(&list2, &nodes[i]);
+    }
+    // merge
+    pj_list_merge_first(&list2, &list);
+    // check (list2).
+    for (i=0, p=list2.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {
+	pj_assert(p->value == i);
+	if (p->value != i) {
+	    return -1;
+	}
+    }
+    // check list is empty
+    pj_assert( pj_list_empty(&list) );
+    if (!pj_list_empty(&list)) {
+	return -1;
+    }
+
+    //
+    // Test insert_nodes_before()
+    //
+    // init list
+    pj_list_init(&list);
+    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes)/2; ++i) {
+	pj_list_insert_before(&list, &nodes[i]);
+    }
+    // chain remaining nodes
+    pj_list_init(&nodes[PJ_SIGNED_ARRAY_SIZE(nodes)/2]);
+    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)/2+1; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {
+	pj_list_insert_before(&nodes[PJ_SIGNED_ARRAY_SIZE(nodes)/2], &nodes[i]);
+    }
+    // insert nodes
+    pj_list_insert_nodes_before(&list, &nodes[PJ_SIGNED_ARRAY_SIZE(nodes)/2]);
+    // check
+    for (i=0, p=list.next; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i, p=p->next) {
+	pj_assert(p->value == i);
+	if (p->value != i) {
+	    return -1;
+	}
+    }
+
+    // erase test.
+    pj_list_init(&list);
+    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {
+	nodes[i].value = i;
+	pj_list_insert_before(&list, &nodes[i]);
+    }
+    for (i=PJ_SIGNED_ARRAY_SIZE(nodes)-1; i>=0; --i) {
+	int j;
+	pj_list_erase(&nodes[i]);
+	for (j=0, p=list.next; j<i; ++j, p=p->next) {
+	    pj_assert(p->value == j);
+	    if (p->value != j) {
+		return -1;
+	    }
+	}
+    }
+
+    // find and search
+    pj_list_init(&list);
+    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {
+	nodes[i].value = i;
+	pj_list_insert_before(&list, &nodes[i]);
+    }
+    for (i=0; i<PJ_SIGNED_ARRAY_SIZE(nodes); ++i) {
+	p = (list_node*) pj_list_find_node(&list, &nodes[i]);
+	pj_assert( p == &nodes[i] );
+	if (p != &nodes[i]) {
+	    return -1;
+	}
+	p = (list_node*) pj_list_search(&list, (void*)(long)i, &compare_node);
+	pj_assert( p == &nodes[i] );
+	if (p != &nodes[i]) {
+	    return -1;
+	}
+    }
+    return 0;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_list_test;
+#endif	/* INCLUDE_LIST_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/main.c b/pjlib/src/pjlib-test/main.c
index 89c0853..fea4cd6 100644
--- a/pjlib/src/pjlib-test/main.c
+++ b/pjlib/src/pjlib-test/main.c
@@ -1,93 +1,93 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-#include <pj/string.h>

-#include <pj/sock.h>

-#include <pj/log.h>

-

-extern int param_echo_sock_type;

-extern const char *param_echo_server;

-extern int param_echo_port;

-

-

-//#if defined(PJ_WIN32) && PJ_WIN32!=0

-#if 0

-#include <windows.h>

-static void boost(void)

-{

-    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);

-}

-#else

-#define boost()

-#endif

-

-#if defined(PJ_SUNOS) && PJ_SUNOS!=0

-#include <signal.h>

-static void init_signals()

-{

-    struct sigaction act;

-

-    memset(&act, 0, sizeof(act));

-    act.sa_handler = SIG_IGN;

-

-    sigaction(SIGALRM, &act, NULL);

-}

-

-#else

-#define init_signals()

-#endif

-

-int main(int argc, char *argv[])

-{

-    int rc;

-

-    boost();

-    init_signals();

-

-    while (argc > 1) {

-        char *arg = argv[--argc];

-

-        if (*arg=='-' && *(arg+1)=='p') {

-            pj_str_t port = pj_str(argv[--argc]);

-

-            param_echo_port = pj_strtoul(&port);

-

-        } else if (*arg=='-' && *(arg+1)=='s') {

-            param_echo_server = argv[--argc];

-

-        } else if (*arg=='-' && *(arg+1)=='t') {

-            pj_str_t type = pj_str(argv[--argc]);

-            

-            if (pj_stricmp2(&type, "tcp")==0)

-                param_echo_sock_type = PJ_SOCK_STREAM;

-            else if (pj_stricmp2(&type, "udp")==0)

-                param_echo_sock_type = PJ_SOCK_DGRAM;

-            else {

-                PJ_LOG(3,("", "error: unknown socket type %s", type.ptr));

-                return 1;

-            }

-        }

-    }

-

-    rc = test_main();

-

-    return rc;

-}

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+#include <pj/string.h>
+#include <pj/sock.h>
+#include <pj/log.h>
+
+extern int param_echo_sock_type;
+extern const char *param_echo_server;
+extern int param_echo_port;
+
+
+//#if defined(PJ_WIN32) && PJ_WIN32!=0
+#if 0
+#include <windows.h>
+static void boost(void)
+{
+    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
+}
+#else
+#define boost()
+#endif
+
+#if defined(PJ_SUNOS) && PJ_SUNOS!=0
+#include <signal.h>
+static void init_signals()
+{
+    struct sigaction act;
+
+    memset(&act, 0, sizeof(act));
+    act.sa_handler = SIG_IGN;
+
+    sigaction(SIGALRM, &act, NULL);
+}
+
+#else
+#define init_signals()
+#endif
+
+int main(int argc, char *argv[])
+{
+    int rc;
+
+    boost();
+    init_signals();
+
+    while (argc > 1) {
+        char *arg = argv[--argc];
+
+        if (*arg=='-' && *(arg+1)=='p') {
+            pj_str_t port = pj_str(argv[--argc]);
+
+            param_echo_port = pj_strtoul(&port);
+
+        } else if (*arg=='-' && *(arg+1)=='s') {
+            param_echo_server = argv[--argc];
+
+        } else if (*arg=='-' && *(arg+1)=='t') {
+            pj_str_t type = pj_str(argv[--argc]);
+            
+            if (pj_stricmp2(&type, "tcp")==0)
+                param_echo_sock_type = PJ_SOCK_STREAM;
+            else if (pj_stricmp2(&type, "udp")==0)
+                param_echo_sock_type = PJ_SOCK_DGRAM;
+            else {
+                PJ_LOG(3,("", "error: unknown socket type %s", type.ptr));
+                return 1;
+            }
+        }
+    }
+
+    rc = test_main();
+
+    return rc;
+}
+
diff --git a/pjlib/src/pjlib-test/main_mod.c b/pjlib/src/pjlib-test/main_mod.c
index 2e7d860..2dada34 100644
--- a/pjlib/src/pjlib-test/main_mod.c
+++ b/pjlib/src/pjlib-test/main_mod.c
@@ -1,39 +1,39 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <linux/module.h>

-#include <linux/kernel.h>

-

-int init_module(void)

-{

-    printk(KERN_INFO "PJLIB test module loaded. Starting tests...\n");

-    

-    test_main();

-

-    /* Prevent module from loading. We've finished test anyway.. */

-    return 1;

-}

-

-void cleanup_module(void)

-{

-    printk(KERN_INFO "PJLIB test module unloading...\n");

-}

-

-MODULE_LICENSE("GPL");

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+int init_module(void)
+{
+    printk(KERN_INFO "PJLIB test module loaded. Starting tests...\n");
+    
+    test_main();
+
+    /* Prevent module from loading. We've finished test anyway.. */
+    return 1;
+}
+
+void cleanup_module(void)
+{
+    printk(KERN_INFO "PJLIB test module unloading...\n");
+}
+
+MODULE_LICENSE("GPL");
+
diff --git a/pjlib/src/pjlib-test/mutex.c b/pjlib/src/pjlib-test/mutex.c
index 29fabd4..877712d 100644
--- a/pjlib/src/pjlib-test/mutex.c
+++ b/pjlib/src/pjlib-test/mutex.c
@@ -1,174 +1,174 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pjlib.h>

-

-#if INCLUDE_MUTEX_TEST

-

-#undef TRACE_

-//#define TRACE_(x)   PJ_LOG(3,x)

-#define TRACE_(x)

-

-/* Test witn non-recursive mutex. */

-static int simple_mutex_test(pj_pool_t *pool)

-{

-    pj_status_t rc;

-    pj_mutex_t *mutex;

-

-    PJ_LOG(3,("", "...testing simple mutex"));

-    

-    /* Create mutex. */

-    TRACE_(("", "....create mutex"));

-    rc = pj_mutex_create( pool, "", PJ_MUTEX_SIMPLE, &mutex);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: pj_mutex_create", rc);

-	return -10;

-    }

-

-    /* Normal lock/unlock cycle. */

-    TRACE_(("", "....lock mutex"));

-    rc = pj_mutex_lock(mutex);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: pj_mutex_lock", rc);

-	return -20;

-    }

-    TRACE_(("", "....unlock mutex"));

-    rc = pj_mutex_unlock(mutex);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: pj_mutex_unlock", rc);

-	return -30;

-    }

-    

-    /* Lock again. */

-    TRACE_(("", "....lock mutex"));

-    rc = pj_mutex_lock(mutex);

-    if (rc != PJ_SUCCESS) return -40;

-

-    /* Try-lock should fail. It should not deadlocked. */

-    TRACE_(("", "....trylock mutex"));

-    rc = pj_mutex_trylock(mutex);

-    if (rc == PJ_SUCCESS)

-	PJ_LOG(3,("", "...info: looks like simple mutex is recursive"));

-

-    /* Unlock and done. */

-    TRACE_(("", "....unlock mutex"));

-    rc = pj_mutex_unlock(mutex);

-    if (rc != PJ_SUCCESS) return -50;

-

-    TRACE_(("", "....destroy mutex"));

-    rc = pj_mutex_destroy(mutex);

-    if (rc != PJ_SUCCESS) return -60;

-

-    TRACE_(("", "....done"));

-    return PJ_SUCCESS;

-}

-

-

-/* Test with recursive mutex. */

-static int recursive_mutex_test(pj_pool_t *pool)

-{

-    pj_status_t rc;

-    pj_mutex_t *mutex;

-

-    PJ_LOG(3,("", "...testing recursive mutex"));

-

-    /* Create mutex. */

-    TRACE_(("", "....create mutex"));

-    rc = pj_mutex_create( pool, "", PJ_MUTEX_RECURSE, &mutex);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: pj_mutex_create", rc);

-	return -10;

-    }

-

-    /* Normal lock/unlock cycle. */

-    TRACE_(("", "....lock mutex"));

-    rc = pj_mutex_lock(mutex);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: pj_mutex_lock", rc);

-	return -20;

-    }

-    TRACE_(("", "....unlock mutex"));

-    rc = pj_mutex_unlock(mutex);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: pj_mutex_unlock", rc);

-	return -30;

-    }

-    

-    /* Lock again. */

-    TRACE_(("", "....lock mutex"));

-    rc = pj_mutex_lock(mutex);

-    if (rc != PJ_SUCCESS) return -40;

-

-    /* Try-lock should NOT fail. . */

-    TRACE_(("", "....trylock mutex"));

-    rc = pj_mutex_trylock(mutex);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: recursive mutex is not recursive!", rc);

-	return -40;

-    }

-

-    /* Locking again should not fail. */

-    TRACE_(("", "....lock mutex"));

-    rc = pj_mutex_lock(mutex);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: recursive mutex is not recursive!", rc);

-	return -45;

-    }

-

-    /* Unlock several times and done. */

-    TRACE_(("", "....unlock mutex 3x"));

-    rc = pj_mutex_unlock(mutex);

-    if (rc != PJ_SUCCESS) return -50;

-    rc = pj_mutex_unlock(mutex);

-    if (rc != PJ_SUCCESS) return -51;

-    rc = pj_mutex_unlock(mutex);

-    if (rc != PJ_SUCCESS) return -52;

-

-    TRACE_(("", "....destroy mutex"));

-    rc = pj_mutex_destroy(mutex);

-    if (rc != PJ_SUCCESS) return -60;

-

-    TRACE_(("", "....done"));

-    return PJ_SUCCESS;

-}

-

-int mutex_test(void)

-{

-    pj_pool_t *pool;

-    int rc;

-

-    pool = pj_pool_create(mem, "", 4000, 4000, NULL);

-

-    rc = simple_mutex_test(pool);

-    if (rc != 0)

-	return rc;

-

-    rc = recursive_mutex_test(pool);

-    if (rc != 0)

-	return rc;

-

-    pj_pool_release(pool);

-

-    return 0;

-}

-

-#else

-int dummy_mutex_test;

-#endif

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib.h>
+
+#if INCLUDE_MUTEX_TEST
+
+#undef TRACE_
+//#define TRACE_(x)   PJ_LOG(3,x)
+#define TRACE_(x)
+
+/* Test witn non-recursive mutex. */
+static int simple_mutex_test(pj_pool_t *pool)
+{
+    pj_status_t rc;
+    pj_mutex_t *mutex;
+
+    PJ_LOG(3,("", "...testing simple mutex"));
+    
+    /* Create mutex. */
+    TRACE_(("", "....create mutex"));
+    rc = pj_mutex_create( pool, "", PJ_MUTEX_SIMPLE, &mutex);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: pj_mutex_create", rc);
+	return -10;
+    }
+
+    /* Normal lock/unlock cycle. */
+    TRACE_(("", "....lock mutex"));
+    rc = pj_mutex_lock(mutex);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: pj_mutex_lock", rc);
+	return -20;
+    }
+    TRACE_(("", "....unlock mutex"));
+    rc = pj_mutex_unlock(mutex);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: pj_mutex_unlock", rc);
+	return -30;
+    }
+    
+    /* Lock again. */
+    TRACE_(("", "....lock mutex"));
+    rc = pj_mutex_lock(mutex);
+    if (rc != PJ_SUCCESS) return -40;
+
+    /* Try-lock should fail. It should not deadlocked. */
+    TRACE_(("", "....trylock mutex"));
+    rc = pj_mutex_trylock(mutex);
+    if (rc == PJ_SUCCESS)
+	PJ_LOG(3,("", "...info: looks like simple mutex is recursive"));
+
+    /* Unlock and done. */
+    TRACE_(("", "....unlock mutex"));
+    rc = pj_mutex_unlock(mutex);
+    if (rc != PJ_SUCCESS) return -50;
+
+    TRACE_(("", "....destroy mutex"));
+    rc = pj_mutex_destroy(mutex);
+    if (rc != PJ_SUCCESS) return -60;
+
+    TRACE_(("", "....done"));
+    return PJ_SUCCESS;
+}
+
+
+/* Test with recursive mutex. */
+static int recursive_mutex_test(pj_pool_t *pool)
+{
+    pj_status_t rc;
+    pj_mutex_t *mutex;
+
+    PJ_LOG(3,("", "...testing recursive mutex"));
+
+    /* Create mutex. */
+    TRACE_(("", "....create mutex"));
+    rc = pj_mutex_create( pool, "", PJ_MUTEX_RECURSE, &mutex);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: pj_mutex_create", rc);
+	return -10;
+    }
+
+    /* Normal lock/unlock cycle. */
+    TRACE_(("", "....lock mutex"));
+    rc = pj_mutex_lock(mutex);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: pj_mutex_lock", rc);
+	return -20;
+    }
+    TRACE_(("", "....unlock mutex"));
+    rc = pj_mutex_unlock(mutex);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: pj_mutex_unlock", rc);
+	return -30;
+    }
+    
+    /* Lock again. */
+    TRACE_(("", "....lock mutex"));
+    rc = pj_mutex_lock(mutex);
+    if (rc != PJ_SUCCESS) return -40;
+
+    /* Try-lock should NOT fail. . */
+    TRACE_(("", "....trylock mutex"));
+    rc = pj_mutex_trylock(mutex);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: recursive mutex is not recursive!", rc);
+	return -40;
+    }
+
+    /* Locking again should not fail. */
+    TRACE_(("", "....lock mutex"));
+    rc = pj_mutex_lock(mutex);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: recursive mutex is not recursive!", rc);
+	return -45;
+    }
+
+    /* Unlock several times and done. */
+    TRACE_(("", "....unlock mutex 3x"));
+    rc = pj_mutex_unlock(mutex);
+    if (rc != PJ_SUCCESS) return -50;
+    rc = pj_mutex_unlock(mutex);
+    if (rc != PJ_SUCCESS) return -51;
+    rc = pj_mutex_unlock(mutex);
+    if (rc != PJ_SUCCESS) return -52;
+
+    TRACE_(("", "....destroy mutex"));
+    rc = pj_mutex_destroy(mutex);
+    if (rc != PJ_SUCCESS) return -60;
+
+    TRACE_(("", "....done"));
+    return PJ_SUCCESS;
+}
+
+int mutex_test(void)
+{
+    pj_pool_t *pool;
+    int rc;
+
+    pool = pj_pool_create(mem, "", 4000, 4000, NULL);
+
+    rc = simple_mutex_test(pool);
+    if (rc != 0)
+	return rc;
+
+    rc = recursive_mutex_test(pool);
+    if (rc != 0)
+	return rc;
+
+    pj_pool_release(pool);
+
+    return 0;
+}
+
+#else
+int dummy_mutex_test;
+#endif
+
diff --git a/pjlib/src/pjlib-test/os.c b/pjlib/src/pjlib-test/os.c
index 2d1b269..7f3c161 100644
--- a/pjlib/src/pjlib-test/os.c
+++ b/pjlib/src/pjlib-test/os.c
@@ -1,19 +1,19 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-int dummy_os_var;

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+int dummy_os_var;
diff --git a/pjlib/src/pjlib-test/pool.c b/pjlib/src/pjlib-test/pool.c
index b20e63a..d48a358 100644
--- a/pjlib/src/pjlib-test/pool.c
+++ b/pjlib/src/pjlib-test/pool.c
@@ -1,172 +1,172 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/pool.h>

-#include <pj/rand.h>

-#include <pj/log.h>

-#include "test.h"

-

-/**

- * \page page_pjlib_pool_test Test: Pool

- *

- * This file provides implementation of \b pool_test(). It tests the

- * functionality of the memory pool.

- *

- *

- * This file is <b>pjlib-test/pool.c</b>

- *

- * \include pjlib-test/pool.c

- */

-

-

-#if INCLUDE_POOL_TEST

-

-#define SIZE	4096

-

-/* Normally we should throw exception when memory alloc fails.

- * Here we do nothing so that the flow will go back to original caller,

- * which will test the result using NULL comparison. Normally caller will

- * catch the exception instead of checking for NULLs.

- */

-static void null_callback(pj_pool_t *pool, pj_size_t size)

-{

-    PJ_UNUSED_ARG(pool);

-    PJ_UNUSED_ARG(size);

-}

-

-#define GET_FREE(p)	(pj_pool_get_capacity(p)-pj_pool_get_used_size(p))

-

-/* Test that the capacity and used size reported by the pool is correct. 

- */

-static int capacity_test(void)

-{

-    pj_pool_t *pool = pj_pool_create(mem, NULL, SIZE, 0, &null_callback);

-    pj_size_t freesize;

-

-    PJ_LOG(3,("test", "...capacity_test()"));

-

-    if (!pool)

-	return -200;

-

-    freesize = GET_FREE(pool);

-

-    if (pj_pool_alloc(pool, freesize) == NULL) {

-	PJ_LOG(3,("test", "...error: wrong freesize %u reported",

-			  freesize));

-	pj_pool_release(pool);

-	return -210;

-    }

-

-    pj_pool_release(pool);

-    return 0;

-}

-

-/* Test function to drain the pool's space. 

- */

-static int drain_test(pj_size_t size, pj_size_t increment)

-{

-    pj_pool_t *pool = pj_pool_create(mem, NULL, size, increment, 

-				     &null_callback);

-    pj_size_t freesize;

-    void *p;

-    int status = 0;

-    

-    PJ_LOG(3,("test", "...drain_test(%d,%d)", size, increment));

-

-    if (!pool)

-	return -10;

-

-    /* Get free size */

-    freesize = GET_FREE(pool);

-    if (freesize < 1) {

-    	status=-15; 

-	goto on_error;

-    }

-

-    /* Drain the pool until there's nothing left. */

-    while (freesize > 0) {

-	int size;

-

-	if (freesize > 255)

-	    size = ((pj_rand() & 0x000000FF) + 4) & ~0x03L;

-	else

-	    size = freesize;

-

-	p = pj_pool_alloc(pool, size);

-	if (!p) {

-	    status=-20; goto on_error;

-	}

-

-	freesize -= size;

-    }

-

-    /* Check that capacity is zero. */

-    if (GET_FREE(pool) != 0) {

-	PJ_LOG(3,("test", "....error: returned free=%u (expecting 0)",

-		  GET_FREE(pool)));

-	status=-30; goto on_error;

-    }

-

-    /* Try to allocate once more */

-    p = pj_pool_alloc(pool, 257);

-    if (!p) {

-	status=-40; goto on_error;

-    }

-

-    /* Check that capacity is NOT zero. */

-    if (GET_FREE(pool) == 0) {

-	status=-50; goto on_error;

-    }

-

-

-on_error:

-    pj_pool_release(pool);

-    return status;

-}

-

-int pool_test(void)

-{

-    enum { LOOP = 2 };

-    int loop;

-    int rc;

-

-    rc = capacity_test();

-    if (rc) return rc;

-

-    for (loop=0; loop<LOOP; ++loop) {

-	/* Test that the pool should grow automaticly. */

-	rc = drain_test(SIZE, SIZE);

-	if (rc != 0) return rc;

-

-	/* Test situation where pool is not allowed to grow. 

- 	 * We expect the test to return correct error.

-	 */

-	rc = drain_test(SIZE, 0);

-	if (rc != -40) return rc;

-    }

-

-    return 0;

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_pool_test;

-#endif	/* INCLUDE_POOL_TEST */

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/pool.h>
+#include <pj/rand.h>
+#include <pj/log.h>
+#include "test.h"
+
+/**
+ * \page page_pjlib_pool_test Test: Pool
+ *
+ * This file provides implementation of \b pool_test(). It tests the
+ * functionality of the memory pool.
+ *
+ *
+ * This file is <b>pjlib-test/pool.c</b>
+ *
+ * \include pjlib-test/pool.c
+ */
+
+
+#if INCLUDE_POOL_TEST
+
+#define SIZE	4096
+
+/* Normally we should throw exception when memory alloc fails.
+ * Here we do nothing so that the flow will go back to original caller,
+ * which will test the result using NULL comparison. Normally caller will
+ * catch the exception instead of checking for NULLs.
+ */
+static void null_callback(pj_pool_t *pool, pj_size_t size)
+{
+    PJ_UNUSED_ARG(pool);
+    PJ_UNUSED_ARG(size);
+}
+
+#define GET_FREE(p)	(pj_pool_get_capacity(p)-pj_pool_get_used_size(p))
+
+/* Test that the capacity and used size reported by the pool is correct. 
+ */
+static int capacity_test(void)
+{
+    pj_pool_t *pool = pj_pool_create(mem, NULL, SIZE, 0, &null_callback);
+    pj_size_t freesize;
+
+    PJ_LOG(3,("test", "...capacity_test()"));
+
+    if (!pool)
+	return -200;
+
+    freesize = GET_FREE(pool);
+
+    if (pj_pool_alloc(pool, freesize) == NULL) {
+	PJ_LOG(3,("test", "...error: wrong freesize %u reported",
+			  freesize));
+	pj_pool_release(pool);
+	return -210;
+    }
+
+    pj_pool_release(pool);
+    return 0;
+}
+
+/* Test function to drain the pool's space. 
+ */
+static int drain_test(pj_size_t size, pj_size_t increment)
+{
+    pj_pool_t *pool = pj_pool_create(mem, NULL, size, increment, 
+				     &null_callback);
+    pj_size_t freesize;
+    void *p;
+    int status = 0;
+    
+    PJ_LOG(3,("test", "...drain_test(%d,%d)", size, increment));
+
+    if (!pool)
+	return -10;
+
+    /* Get free size */
+    freesize = GET_FREE(pool);
+    if (freesize < 1) {
+    	status=-15; 
+	goto on_error;
+    }
+
+    /* Drain the pool until there's nothing left. */
+    while (freesize > 0) {
+	int size;
+
+	if (freesize > 255)
+	    size = ((pj_rand() & 0x000000FF) + 4) & ~0x03L;
+	else
+	    size = freesize;
+
+	p = pj_pool_alloc(pool, size);
+	if (!p) {
+	    status=-20; goto on_error;
+	}
+
+	freesize -= size;
+    }
+
+    /* Check that capacity is zero. */
+    if (GET_FREE(pool) != 0) {
+	PJ_LOG(3,("test", "....error: returned free=%u (expecting 0)",
+		  GET_FREE(pool)));
+	status=-30; goto on_error;
+    }
+
+    /* Try to allocate once more */
+    p = pj_pool_alloc(pool, 257);
+    if (!p) {
+	status=-40; goto on_error;
+    }
+
+    /* Check that capacity is NOT zero. */
+    if (GET_FREE(pool) == 0) {
+	status=-50; goto on_error;
+    }
+
+
+on_error:
+    pj_pool_release(pool);
+    return status;
+}
+
+int pool_test(void)
+{
+    enum { LOOP = 2 };
+    int loop;
+    int rc;
+
+    rc = capacity_test();
+    if (rc) return rc;
+
+    for (loop=0; loop<LOOP; ++loop) {
+	/* Test that the pool should grow automaticly. */
+	rc = drain_test(SIZE, SIZE);
+	if (rc != 0) return rc;
+
+	/* Test situation where pool is not allowed to grow. 
+ 	 * We expect the test to return correct error.
+	 */
+	rc = drain_test(SIZE, 0);
+	if (rc != -40) return rc;
+    }
+
+    return 0;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_pool_test;
+#endif	/* INCLUDE_POOL_TEST */
+
diff --git a/pjlib/src/pjlib-test/pool_perf.c b/pjlib/src/pjlib-test/pool_perf.c
index a7c8fba..6bc6dcf 100644
--- a/pjlib/src/pjlib-test/pool_perf.c
+++ b/pjlib/src/pjlib-test/pool_perf.c
@@ -1,140 +1,140 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-#if INCLUDE_POOL_PERF_TEST

-

-#include <pjlib.h>

-#include <pj/compat/malloc.h>

-

-#if !PJ_HAS_HIGH_RES_TIMER

-# error Need high resolution timer for this test.

-#endif

-

-#define THIS_FILE   "test"

-

-#define LOOP	    10

-#define COUNT	    1024

-static unsigned	    sizes[COUNT];

-#define MIN_SIZE    4

-#define MAX_SIZE    512

-static unsigned total_size;

-

-static int pool_test_pool()

-{

-    int i;

-    pj_pool_t *pool = pj_pool_create(mem, NULL, total_size + 4*COUNT, 0, NULL);

-    if (!pool)

-	return -1;

-

-    for (i=0; i<COUNT; ++i) {

-	char *p;

-	if ( (p=(char*)pj_pool_alloc(pool, sizes[i])) == NULL)

-	    return -1;

-	*p = '\0';

-    }

-

-    pj_pool_release(pool);

-    return 0;

-}

-

-static int pool_test_malloc_free()

-{

-    char *p[COUNT];

-    int i;

-

-    for (i=0; i<COUNT; ++i) {

-	p[i] = (char*)malloc(sizes[i]);

-	if (!p[i]) {

-	    // Don't care for memory leak in this test

-	    return -1;

-	}

-	*p[i] = '\0';

-    }

-

-    for (i=0; i<COUNT; ++i) {

-	free(p[i]);

-    }

-

-    return 0;

-}

-

-int pool_perf_test()

-{

-    unsigned i;

-    pj_uint32_t pool_time=0, malloc_time=0, pool_time2=0;

-    pj_timestamp start, end;

-    pj_uint32_t best, worst;

-

-    // Initialize sizes.

-    for (i=0; i<COUNT; ++i) {

-	sizes[i] = MIN_SIZE + pj_rand() % MAX_SIZE;

-	total_size += sizes[i];

-    }

-

-    PJ_LOG(3, (THIS_FILE, "Benchmarking pool.."));

-

-    // Warmup

-    pool_test_pool();

-    pool_test_malloc_free();

-

-    for (i=0; i<LOOP; ++i) {

-	pj_get_timestamp(&start);

-	if (pool_test_pool()) {

-	    return 1;

-	}

-	pj_get_timestamp(&end);

-	pool_time += (end.u32.lo - start.u32.lo);

-

-	pj_get_timestamp(&start);

-	if (pool_test_malloc_free()) {

-	    return 2;

-	}

-	pj_get_timestamp(&end);

-	malloc_time += (end.u32.lo - start.u32.lo);

-

-	pj_get_timestamp(&start);

-	if (pool_test_pool()) {

-	    return 4;

-	}

-	pj_get_timestamp(&end);

-	pool_time2 += (end.u32.lo - start.u32.lo);

-    }

-

-    PJ_LOG(4, (THIS_FILE, "..LOOP count:                        %u", LOOP));

-    PJ_LOG(4, (THIS_FILE, "..number of alloc/dealloc per loop:  %u", COUNT));

-    PJ_LOG(4, (THIS_FILE, "..pool allocation/deallocation time: %u", pool_time));

-    PJ_LOG(4, (THIS_FILE, "..malloc/free time:                  %u", malloc_time));

-    PJ_LOG(4, (THIS_FILE, "..pool again, second invocation:     %u", pool_time2));

-

-    if (pool_time2==0) pool_time2=1;

-    if (pool_time < pool_time2)

-	best = pool_time, worst = pool_time2;

-    else

-	best = pool_time2, worst = pool_time;

-

-    PJ_LOG(3, (THIS_FILE, "..malloc Speedup best=%dx, worst=%dx", 

-			  (int)(malloc_time/best),

-			  (int)(malloc_time/worst)));

-    return 0;

-}

-

-

-#endif	/* INCLUDE_POOL_PERF_TEST */

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+#if INCLUDE_POOL_PERF_TEST
+
+#include <pjlib.h>
+#include <pj/compat/malloc.h>
+
+#if !PJ_HAS_HIGH_RES_TIMER
+# error Need high resolution timer for this test.
+#endif
+
+#define THIS_FILE   "test"
+
+#define LOOP	    10
+#define COUNT	    1024
+static unsigned	    sizes[COUNT];
+#define MIN_SIZE    4
+#define MAX_SIZE    512
+static unsigned total_size;
+
+static int pool_test_pool()
+{
+    int i;
+    pj_pool_t *pool = pj_pool_create(mem, NULL, total_size + 4*COUNT, 0, NULL);
+    if (!pool)
+	return -1;
+
+    for (i=0; i<COUNT; ++i) {
+	char *p;
+	if ( (p=(char*)pj_pool_alloc(pool, sizes[i])) == NULL)
+	    return -1;
+	*p = '\0';
+    }
+
+    pj_pool_release(pool);
+    return 0;
+}
+
+static int pool_test_malloc_free()
+{
+    char *p[COUNT];
+    int i;
+
+    for (i=0; i<COUNT; ++i) {
+	p[i] = (char*)malloc(sizes[i]);
+	if (!p[i]) {
+	    // Don't care for memory leak in this test
+	    return -1;
+	}
+	*p[i] = '\0';
+    }
+
+    for (i=0; i<COUNT; ++i) {
+	free(p[i]);
+    }
+
+    return 0;
+}
+
+int pool_perf_test()
+{
+    unsigned i;
+    pj_uint32_t pool_time=0, malloc_time=0, pool_time2=0;
+    pj_timestamp start, end;
+    pj_uint32_t best, worst;
+
+    // Initialize sizes.
+    for (i=0; i<COUNT; ++i) {
+	sizes[i] = MIN_SIZE + pj_rand() % MAX_SIZE;
+	total_size += sizes[i];
+    }
+
+    PJ_LOG(3, (THIS_FILE, "Benchmarking pool.."));
+
+    // Warmup
+    pool_test_pool();
+    pool_test_malloc_free();
+
+    for (i=0; i<LOOP; ++i) {
+	pj_get_timestamp(&start);
+	if (pool_test_pool()) {
+	    return 1;
+	}
+	pj_get_timestamp(&end);
+	pool_time += (end.u32.lo - start.u32.lo);
+
+	pj_get_timestamp(&start);
+	if (pool_test_malloc_free()) {
+	    return 2;
+	}
+	pj_get_timestamp(&end);
+	malloc_time += (end.u32.lo - start.u32.lo);
+
+	pj_get_timestamp(&start);
+	if (pool_test_pool()) {
+	    return 4;
+	}
+	pj_get_timestamp(&end);
+	pool_time2 += (end.u32.lo - start.u32.lo);
+    }
+
+    PJ_LOG(4, (THIS_FILE, "..LOOP count:                        %u", LOOP));
+    PJ_LOG(4, (THIS_FILE, "..number of alloc/dealloc per loop:  %u", COUNT));
+    PJ_LOG(4, (THIS_FILE, "..pool allocation/deallocation time: %u", pool_time));
+    PJ_LOG(4, (THIS_FILE, "..malloc/free time:                  %u", malloc_time));
+    PJ_LOG(4, (THIS_FILE, "..pool again, second invocation:     %u", pool_time2));
+
+    if (pool_time2==0) pool_time2=1;
+    if (pool_time < pool_time2)
+	best = pool_time, worst = pool_time2;
+    else
+	best = pool_time2, worst = pool_time;
+
+    PJ_LOG(3, (THIS_FILE, "..malloc Speedup best=%dx, worst=%dx", 
+			  (int)(malloc_time/best),
+			  (int)(malloc_time/worst)));
+    return 0;
+}
+
+
+#endif	/* INCLUDE_POOL_PERF_TEST */
+
diff --git a/pjlib/src/pjlib-test/rand.c b/pjlib/src/pjlib-test/rand.c
index 33e8107..6edfbd2 100644
--- a/pjlib/src/pjlib-test/rand.c
+++ b/pjlib/src/pjlib-test/rand.c
@@ -1,53 +1,53 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/rand.h>

-#include <pj/log.h>

-#include "test.h"

-

-#if INCLUDE_RAND_TEST

-

-#define COUNT  1024

-static int values[COUNT];

-

-/*

- * rand_test(), simply generates COUNT number of random number and

- * check that there's no duplicate numbers.

- */

-int rand_test(void)

-{

-    int i;

-

-    for (i=0; i<COUNT; ++i) {

-	int j;

-

-	values[i] = pj_rand();

-	for (j=0; j<i; ++j) {

-	    if (values[i] == values[j]) {

-		PJ_LOG(3,("test", "error: duplicate value %d at %d-th index",

-			 values[i], i));

-		return -10;

-	    }

-	}

-    }

-

-    return 0;

-}

-

-#endif	/* INCLUDE_RAND_TEST */

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/rand.h>
+#include <pj/log.h>
+#include "test.h"
+
+#if INCLUDE_RAND_TEST
+
+#define COUNT  1024
+static int values[COUNT];
+
+/*
+ * rand_test(), simply generates COUNT number of random number and
+ * check that there's no duplicate numbers.
+ */
+int rand_test(void)
+{
+    int i;
+
+    for (i=0; i<COUNT; ++i) {
+	int j;
+
+	values[i] = pj_rand();
+	for (j=0; j<i; ++j) {
+	    if (values[i] == values[j]) {
+		PJ_LOG(3,("test", "error: duplicate value %d at %d-th index",
+			 values[i], i));
+		return -10;
+	    }
+	}
+    }
+
+    return 0;
+}
+
+#endif	/* INCLUDE_RAND_TEST */
+
diff --git a/pjlib/src/pjlib-test/rbtree.c b/pjlib/src/pjlib-test/rbtree.c
index 588e58a..dc10218 100644
--- a/pjlib/src/pjlib-test/rbtree.c
+++ b/pjlib/src/pjlib-test/rbtree.c
@@ -1,167 +1,167 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-#if INCLUDE_RBTREE_TEST

-

-#include <pjlib.h>

-

-#define LOOP	    32

-#define MIN_COUNT   64

-#define MAX_COUNT   (LOOP * MIN_COUNT)

-#define STRSIZE	    16

-#define THIS_FILE   "rbtree_test"

-

-typedef struct node_key

-{

-    pj_uint32_t hash;

-    char str[STRSIZE];

-} node_key;

-

-static int compare_node(const node_key *k1, const node_key *k2)

-{

-    if (k1->hash == k2->hash) {

-	return strcmp(k1->str, k2->str);

-    } else {

-	return k1->hash	< k2->hash ? -1 : 1;

-    }

-}

-

-void randomize_string(char *str, int len)

-{

-    int i;

-    for (i=0; i<len-1; ++i)

-	str[i] = (char)('a' + pj_rand() % 26);

-    str[len-1] = '\0';

-}

-

-static int test(void)

-{

-    pj_rbtree rb;

-    node_key *key;

-    pj_rbtree_node *node;

-    pj_pool_t *pool;

-    int err=0;

-    int count = MIN_COUNT;

-    int i;

-    unsigned size;

-

-    pj_rbtree_init(&rb, (pj_rbtree_comp*)&compare_node);

-    size = MAX_COUNT*(sizeof(*key)+PJ_RBTREE_NODE_SIZE) + 

-			   PJ_RBTREE_SIZE + PJ_POOL_SIZE;

-    pool = pj_pool_create( mem, "pool", size, 0, NULL);

-    if (!pool) {

-	PJ_LOG(3,("test", "...error: creating pool of %u bytes", size));

-	return -10;

-    }

-

-    key = (node_key *)pj_pool_alloc(pool, MAX_COUNT*sizeof(*key));

-    if (!key)

-	return -20;

-

-    node = (pj_rbtree_node*)pj_pool_alloc(pool, MAX_COUNT*sizeof(*node));

-    if (!node)

-	return -30;

-

-    for (i=0; i<LOOP; ++i) {

-	int j;

-	pj_rbtree_node *prev, *it;

-	pj_timestamp t1, t2, t_setup, t_insert, t_search, t_erase;

-

-	pj_assert(rb.size == 0);

-

-	t_setup.u32.lo = t_insert.u32.lo = t_search.u32.lo = t_erase.u32.lo = 0;

-

-	for (j=0; j<count; j++) {

-	    randomize_string(key[j].str, STRSIZE);

-

-	    pj_get_timestamp(&t1);

-	    node[j].key = &key[j];

-	    node[j].user_data = key[j].str;

-	    key[j].hash = pj_hash_calc(0, key[j].str, PJ_HASH_KEY_STRING);

-	    pj_get_timestamp(&t2);

-	    t_setup.u32.lo += (t2.u32.lo - t1.u32.lo);

-

-	    pj_get_timestamp(&t1);

-	    pj_rbtree_insert(&rb, &node[j]);

-	    pj_get_timestamp(&t2);

-	    t_insert.u32.lo += (t2.u32.lo - t1.u32.lo);

-	}

-

-	pj_assert(rb.size == (unsigned)count);

-

-	// Iterate key, make sure they're sorted.

-	prev = NULL;

-	it = pj_rbtree_first(&rb);

-	while (it) {

-	    if (prev) {

-		if (compare_node((node_key*)prev->key,(node_key*)it->key)>=0) {

-		    ++err;

-		    PJ_LOG(3, (THIS_FILE, "Error: %s >= %s", 

-			       (char*)prev->user_data, (char*)it->user_data));

-		}

-	    }

-	    prev = it;

-	    it = pj_rbtree_next(&rb, it);

-	}

-

-	// Search.

-	for (j=0; j<count; j++) {

-	    pj_get_timestamp(&t1);

-	    it = pj_rbtree_find(&rb, &key[j]);

-	    pj_get_timestamp(&t2);

-	    t_search.u32.lo += (t2.u32.lo - t1.u32.lo);

-

-	    pj_assert(it != NULL);

-	    if (it == NULL)

-		++err;

-	}

-

-	// Erase node.

-	for (j=0; j<count; j++) {

-	    pj_get_timestamp(&t1);

-	    it = pj_rbtree_erase(&rb, &node[j]);

-	    pj_get_timestamp(&t2);

-	    t_erase.u32.lo += (t2.u32.lo - t1.u32.lo);

-	}

-

-	PJ_LOG(4, (THIS_FILE, 

-		"...count:%d, setup:%d, insert:%d, search:%d, erase:%d",

-		count,

-		t_setup.u32.lo / count, t_insert.u32.lo / count,

-		t_search.u32.lo / count, t_erase.u32.lo / count));

-

-	count = 2 * count;

-	if (count > MAX_COUNT)

-	    break;

-    }

-

-    pj_pool_release(pool);

-    return err;

-}

-

-

-int rbtree_test()

-{

-    return test();

-}

-

-#endif	/* INCLUDE_RBTREE_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+#if INCLUDE_RBTREE_TEST
+
+#include <pjlib.h>
+
+#define LOOP	    32
+#define MIN_COUNT   64
+#define MAX_COUNT   (LOOP * MIN_COUNT)
+#define STRSIZE	    16
+#define THIS_FILE   "rbtree_test"
+
+typedef struct node_key
+{
+    pj_uint32_t hash;
+    char str[STRSIZE];
+} node_key;
+
+static int compare_node(const node_key *k1, const node_key *k2)
+{
+    if (k1->hash == k2->hash) {
+	return strcmp(k1->str, k2->str);
+    } else {
+	return k1->hash	< k2->hash ? -1 : 1;
+    }
+}
+
+void randomize_string(char *str, int len)
+{
+    int i;
+    for (i=0; i<len-1; ++i)
+	str[i] = (char)('a' + pj_rand() % 26);
+    str[len-1] = '\0';
+}
+
+static int test(void)
+{
+    pj_rbtree rb;
+    node_key *key;
+    pj_rbtree_node *node;
+    pj_pool_t *pool;
+    int err=0;
+    int count = MIN_COUNT;
+    int i;
+    unsigned size;
+
+    pj_rbtree_init(&rb, (pj_rbtree_comp*)&compare_node);
+    size = MAX_COUNT*(sizeof(*key)+PJ_RBTREE_NODE_SIZE) + 
+			   PJ_RBTREE_SIZE + PJ_POOL_SIZE;
+    pool = pj_pool_create( mem, "pool", size, 0, NULL);
+    if (!pool) {
+	PJ_LOG(3,("test", "...error: creating pool of %u bytes", size));
+	return -10;
+    }
+
+    key = (node_key *)pj_pool_alloc(pool, MAX_COUNT*sizeof(*key));
+    if (!key)
+	return -20;
+
+    node = (pj_rbtree_node*)pj_pool_alloc(pool, MAX_COUNT*sizeof(*node));
+    if (!node)
+	return -30;
+
+    for (i=0; i<LOOP; ++i) {
+	int j;
+	pj_rbtree_node *prev, *it;
+	pj_timestamp t1, t2, t_setup, t_insert, t_search, t_erase;
+
+	pj_assert(rb.size == 0);
+
+	t_setup.u32.lo = t_insert.u32.lo = t_search.u32.lo = t_erase.u32.lo = 0;
+
+	for (j=0; j<count; j++) {
+	    randomize_string(key[j].str, STRSIZE);
+
+	    pj_get_timestamp(&t1);
+	    node[j].key = &key[j];
+	    node[j].user_data = key[j].str;
+	    key[j].hash = pj_hash_calc(0, key[j].str, PJ_HASH_KEY_STRING);
+	    pj_get_timestamp(&t2);
+	    t_setup.u32.lo += (t2.u32.lo - t1.u32.lo);
+
+	    pj_get_timestamp(&t1);
+	    pj_rbtree_insert(&rb, &node[j]);
+	    pj_get_timestamp(&t2);
+	    t_insert.u32.lo += (t2.u32.lo - t1.u32.lo);
+	}
+
+	pj_assert(rb.size == (unsigned)count);
+
+	// Iterate key, make sure they're sorted.
+	prev = NULL;
+	it = pj_rbtree_first(&rb);
+	while (it) {
+	    if (prev) {
+		if (compare_node((node_key*)prev->key,(node_key*)it->key)>=0) {
+		    ++err;
+		    PJ_LOG(3, (THIS_FILE, "Error: %s >= %s", 
+			       (char*)prev->user_data, (char*)it->user_data));
+		}
+	    }
+	    prev = it;
+	    it = pj_rbtree_next(&rb, it);
+	}
+
+	// Search.
+	for (j=0; j<count; j++) {
+	    pj_get_timestamp(&t1);
+	    it = pj_rbtree_find(&rb, &key[j]);
+	    pj_get_timestamp(&t2);
+	    t_search.u32.lo += (t2.u32.lo - t1.u32.lo);
+
+	    pj_assert(it != NULL);
+	    if (it == NULL)
+		++err;
+	}
+
+	// Erase node.
+	for (j=0; j<count; j++) {
+	    pj_get_timestamp(&t1);
+	    it = pj_rbtree_erase(&rb, &node[j]);
+	    pj_get_timestamp(&t2);
+	    t_erase.u32.lo += (t2.u32.lo - t1.u32.lo);
+	}
+
+	PJ_LOG(4, (THIS_FILE, 
+		"...count:%d, setup:%d, insert:%d, search:%d, erase:%d",
+		count,
+		t_setup.u32.lo / count, t_insert.u32.lo / count,
+		t_search.u32.lo / count, t_erase.u32.lo / count));
+
+	count = 2 * count;
+	if (count > MAX_COUNT)
+	    break;
+    }
+
+    pj_pool_release(pool);
+    return err;
+}
+
+
+int rbtree_test()
+{
+    return test();
+}
+
+#endif	/* INCLUDE_RBTREE_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/select.c b/pjlib/src/pjlib-test/select.c
index 4418473..ed2edd4 100644
--- a/pjlib/src/pjlib-test/select.c
+++ b/pjlib/src/pjlib-test/select.c
@@ -1,217 +1,217 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-/**

- * \page page_pjlib_select_test Test: Socket Select()

- *

- * This file provides implementation of \b select_test(). It tests the

- * functionality of the pj_sock_select() API.

- *

- *

- * This file is <b>pjlib-test/select.c</b>

- *

- * \include pjlib-test/select.c

- */

-

-

-#if INCLUDE_SELECT_TEST

-

-#include <pj/sock.h>

-#include <pj/sock_select.h>

-#include <pj/log.h>

-#include <pj/string.h>

-#include <pj/assert.h>

-#include <pj/os.h>

-#include <pj/errno.h>

-

-enum

-{

-    READ_FDS,

-    WRITE_FDS,

-    EXCEPT_FDS

-};

-

-#define UDP_PORT    51232

-#define THIS_FILE   "select_test"

-

-/*

- * do_select()

- *

- * Perform pj_sock_select() and find out which sockets

- * are signalled.

- */    

-static int do_select( pj_sock_t sock1, pj_sock_t sock2,

-		      int setcount[])

-{

-    pj_fd_set_t fds[3];

-    pj_time_val timeout;

-    int i, n;

-    

-    for (i=0; i<3; ++i) {

-        PJ_FD_ZERO(&fds[i]);

-        PJ_FD_SET(sock1, &fds[i]);

-        PJ_FD_SET(sock2, &fds[i]);

-        setcount[i] = 0;

-    }

-

-    timeout.sec = 1;

-    timeout.msec = 0;

-

-    n = pj_sock_select(FD_SETSIZE, &fds[0], &fds[1], &fds[2],

-		       &timeout);

-    if (n < 0)

-        return n;

-    if (n == 0)

-        return 0;

-

-    for (i=0; i<3; ++i) {

-        if (PJ_FD_ISSET(sock1, &fds[i]))

-            setcount[i]++;

-        if (PJ_FD_ISSET(sock2, &fds[i]))

-	    setcount[i]++;

-    }

-

-    return n;

-}

-

-/*

- * select_test()

- *

- * Test main entry.

- */

-int select_test()

-{

-    pj_sock_t udp1=PJ_INVALID_SOCKET, udp2=PJ_INVALID_SOCKET;

-    pj_sockaddr_in udp_addr;

-    int status;

-    int setcount[3];

-    pj_str_t s;

-    const char data[] = "hello";

-    const int datalen = 5;

-    pj_ssize_t sent, received;

-    char buf[10];

-    pj_status_t rc;

-

-    PJ_LOG(3, (THIS_FILE, "...Testing simple UDP select()"));

-    

-    // Create two UDP sockets.

-    rc = pj_sock_socket( PJ_AF_INET, PJ_SOCK_DGRAM, 0, &udp1);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error: unable to create socket", rc);

-	status=-10; goto on_return;

-    }

-    rc = pj_sock_socket( PJ_AF_INET, PJ_SOCK_DGRAM, 0, &udp2);

-    if (udp2 == PJ_INVALID_SOCKET) {

-        app_perror("...error: unable to create socket", rc);

-	status=-20; goto on_return;

-    }

-

-    // Bind one of the UDP socket.

-    pj_memset(&udp_addr, 0, sizeof(udp_addr));

-    udp_addr.sin_family = PJ_AF_INET;

-    udp_addr.sin_port = UDP_PORT;

-    udp_addr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));

-

-    if (pj_sock_bind(udp2, &udp_addr, sizeof(udp_addr))) {

-	status=-30; goto on_return;

-    }

-

-    // Send data.

-    sent = datalen;

-    rc = pj_sock_sendto(udp1, data, &sent, 0, &udp_addr, sizeof(udp_addr));

-    if (rc != PJ_SUCCESS || sent != datalen) {

-        app_perror("...error: sendto() error", rc);

-	status=-40; goto on_return;

-    }

-

-    // Check that socket is marked as reable.

-    // Note that select() may also report that sockets are writable.

-    status = do_select(udp1, udp2, setcount);

-    if (status < 0) {

-	char errbuf[128];

-        pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf));

-	PJ_LOG(1,(THIS_FILE, "...error: %s", errbuf));

-	status=-50; goto on_return;

-    }

-    if (status == 0) {

-	status=-60; goto on_return;

-    }

-

-    if (setcount[READ_FDS] != 1) {

-	status=-70; goto on_return;

-    }

-    if (setcount[WRITE_FDS] != 0) {

-	if (setcount[WRITE_FDS] == 2) {

-	    PJ_LOG(3,(THIS_FILE, "...info: system reports writable sockets"));

-	} else {

-	    status=-80; goto on_return;

-	}

-    } else {

-	PJ_LOG(3,(THIS_FILE, 

-		  "...info: system doesn't report writable sockets"));

-    }

-    if (setcount[EXCEPT_FDS] != 0) {

-	status=-90; goto on_return;

-    }

-

-    // Read the socket to clear readable sockets.

-    received = sizeof(buf);

-    rc = pj_sock_recv(udp2, buf, &received, 0);

-    if (rc != PJ_SUCCESS || received != 5) {

-	status=-100; goto on_return;

-    }

-    

-    status = 0;

-

-    // Test timeout on the read part.

-    // This won't necessarily return zero, as select() may report that

-    // sockets are writable.

-    setcount[0] = setcount[1] = setcount[2] = 0;

-    status = do_select(udp1, udp2, setcount);

-    if (status != 0 && status != setcount[WRITE_FDS]) {

-	PJ_LOG(3,(THIS_FILE, "...error: expecting timeout but got %d sks set",

-			     status));

-	PJ_LOG(3,(THIS_FILE, "          rdset: %d, wrset: %d, exset: %d",

-			     setcount[0], setcount[1], setcount[2]));

-	status = -110; goto on_return;

-    }

-    if (setcount[READ_FDS] != 0) {

-	PJ_LOG(3,(THIS_FILE, "...error: readable socket not expected"));

-	status = -120; goto on_return;

-    }

-

-    status = 0;

-

-on_return:

-    if (udp1 != PJ_INVALID_SOCKET)

-	pj_sock_close(udp1);

-    if (udp2 != PJ_INVALID_SOCKET)

-	pj_sock_close(udp2);

-    return status;

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_select_test;

-#endif	/* INCLUDE_SELECT_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+/**
+ * \page page_pjlib_select_test Test: Socket Select()
+ *
+ * This file provides implementation of \b select_test(). It tests the
+ * functionality of the pj_sock_select() API.
+ *
+ *
+ * This file is <b>pjlib-test/select.c</b>
+ *
+ * \include pjlib-test/select.c
+ */
+
+
+#if INCLUDE_SELECT_TEST
+
+#include <pj/sock.h>
+#include <pj/sock_select.h>
+#include <pj/log.h>
+#include <pj/string.h>
+#include <pj/assert.h>
+#include <pj/os.h>
+#include <pj/errno.h>
+
+enum
+{
+    READ_FDS,
+    WRITE_FDS,
+    EXCEPT_FDS
+};
+
+#define UDP_PORT    51232
+#define THIS_FILE   "select_test"
+
+/*
+ * do_select()
+ *
+ * Perform pj_sock_select() and find out which sockets
+ * are signalled.
+ */    
+static int do_select( pj_sock_t sock1, pj_sock_t sock2,
+		      int setcount[])
+{
+    pj_fd_set_t fds[3];
+    pj_time_val timeout;
+    int i, n;
+    
+    for (i=0; i<3; ++i) {
+        PJ_FD_ZERO(&fds[i]);
+        PJ_FD_SET(sock1, &fds[i]);
+        PJ_FD_SET(sock2, &fds[i]);
+        setcount[i] = 0;
+    }
+
+    timeout.sec = 1;
+    timeout.msec = 0;
+
+    n = pj_sock_select(FD_SETSIZE, &fds[0], &fds[1], &fds[2],
+		       &timeout);
+    if (n < 0)
+        return n;
+    if (n == 0)
+        return 0;
+
+    for (i=0; i<3; ++i) {
+        if (PJ_FD_ISSET(sock1, &fds[i]))
+            setcount[i]++;
+        if (PJ_FD_ISSET(sock2, &fds[i]))
+	    setcount[i]++;
+    }
+
+    return n;
+}
+
+/*
+ * select_test()
+ *
+ * Test main entry.
+ */
+int select_test()
+{
+    pj_sock_t udp1=PJ_INVALID_SOCKET, udp2=PJ_INVALID_SOCKET;
+    pj_sockaddr_in udp_addr;
+    int status;
+    int setcount[3];
+    pj_str_t s;
+    const char data[] = "hello";
+    const int datalen = 5;
+    pj_ssize_t sent, received;
+    char buf[10];
+    pj_status_t rc;
+
+    PJ_LOG(3, (THIS_FILE, "...Testing simple UDP select()"));
+    
+    // Create two UDP sockets.
+    rc = pj_sock_socket( PJ_AF_INET, PJ_SOCK_DGRAM, 0, &udp1);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error: unable to create socket", rc);
+	status=-10; goto on_return;
+    }
+    rc = pj_sock_socket( PJ_AF_INET, PJ_SOCK_DGRAM, 0, &udp2);
+    if (udp2 == PJ_INVALID_SOCKET) {
+        app_perror("...error: unable to create socket", rc);
+	status=-20; goto on_return;
+    }
+
+    // Bind one of the UDP socket.
+    pj_memset(&udp_addr, 0, sizeof(udp_addr));
+    udp_addr.sin_family = PJ_AF_INET;
+    udp_addr.sin_port = UDP_PORT;
+    udp_addr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));
+
+    if (pj_sock_bind(udp2, &udp_addr, sizeof(udp_addr))) {
+	status=-30; goto on_return;
+    }
+
+    // Send data.
+    sent = datalen;
+    rc = pj_sock_sendto(udp1, data, &sent, 0, &udp_addr, sizeof(udp_addr));
+    if (rc != PJ_SUCCESS || sent != datalen) {
+        app_perror("...error: sendto() error", rc);
+	status=-40; goto on_return;
+    }
+
+    // Check that socket is marked as reable.
+    // Note that select() may also report that sockets are writable.
+    status = do_select(udp1, udp2, setcount);
+    if (status < 0) {
+	char errbuf[128];
+        pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf));
+	PJ_LOG(1,(THIS_FILE, "...error: %s", errbuf));
+	status=-50; goto on_return;
+    }
+    if (status == 0) {
+	status=-60; goto on_return;
+    }
+
+    if (setcount[READ_FDS] != 1) {
+	status=-70; goto on_return;
+    }
+    if (setcount[WRITE_FDS] != 0) {
+	if (setcount[WRITE_FDS] == 2) {
+	    PJ_LOG(3,(THIS_FILE, "...info: system reports writable sockets"));
+	} else {
+	    status=-80; goto on_return;
+	}
+    } else {
+	PJ_LOG(3,(THIS_FILE, 
+		  "...info: system doesn't report writable sockets"));
+    }
+    if (setcount[EXCEPT_FDS] != 0) {
+	status=-90; goto on_return;
+    }
+
+    // Read the socket to clear readable sockets.
+    received = sizeof(buf);
+    rc = pj_sock_recv(udp2, buf, &received, 0);
+    if (rc != PJ_SUCCESS || received != 5) {
+	status=-100; goto on_return;
+    }
+    
+    status = 0;
+
+    // Test timeout on the read part.
+    // This won't necessarily return zero, as select() may report that
+    // sockets are writable.
+    setcount[0] = setcount[1] = setcount[2] = 0;
+    status = do_select(udp1, udp2, setcount);
+    if (status != 0 && status != setcount[WRITE_FDS]) {
+	PJ_LOG(3,(THIS_FILE, "...error: expecting timeout but got %d sks set",
+			     status));
+	PJ_LOG(3,(THIS_FILE, "          rdset: %d, wrset: %d, exset: %d",
+			     setcount[0], setcount[1], setcount[2]));
+	status = -110; goto on_return;
+    }
+    if (setcount[READ_FDS] != 0) {
+	PJ_LOG(3,(THIS_FILE, "...error: readable socket not expected"));
+	status = -120; goto on_return;
+    }
+
+    status = 0;
+
+on_return:
+    if (udp1 != PJ_INVALID_SOCKET)
+	pj_sock_close(udp1);
+    if (udp2 != PJ_INVALID_SOCKET)
+	pj_sock_close(udp2);
+    return status;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_select_test;
+#endif	/* INCLUDE_SELECT_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/sleep.c b/pjlib/src/pjlib-test/sleep.c
index 1af794e..5732a16 100644
--- a/pjlib/src/pjlib-test/sleep.c
+++ b/pjlib/src/pjlib-test/sleep.c
@@ -1,200 +1,200 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-/**

- * \page page_pjlib_sleep_test Test: Sleep, Time, and Timestamp

- *

- * This file provides implementation of \b sleep_test().

- *

- * \section sleep_test_sec Scope of the Test

- *

- * This tests:

- *  - whether pj_thread_sleep() works.

- *  - whether pj_gettimeofday() works.

- *  - whether pj_get_timestamp() and friends works.

- *

- * API tested:

- *  - pj_thread_sleep()

- *  - pj_gettimeofday()

- *  - PJ_TIME_VAL_SUB()

- *  - PJ_TIME_VAL_LTE()

- *  - pj_get_timestamp()

- *  - pj_get_timestamp_freq() (implicitly)

- *  - pj_elapsed_time()

- *  - pj_elapsed_usec()

- *

- *

- * This file is <b>pjlib-test/sleep.c</b>

- *

- * \include pjlib-test/sleep.c

- */

-

-#if INCLUDE_SLEEP_TEST

-

-#include <pjlib.h>

-

-#define THIS_FILE   "sleep_test"

-

-static int simple_sleep_test(void)

-{

-    enum { COUNT = 5 };

-    int i;

-    pj_status_t rc;

-    

-    PJ_LOG(3,(THIS_FILE, "..will write messages every 1 second:"));

-    

-    for (i=0; i<COUNT; ++i) {

-	rc = pj_thread_sleep(1000);

-	if (rc != PJ_SUCCESS) {

-	    app_perror("...error: pj_thread_sleep()", rc);

-	    return -10;

-	}

-	PJ_LOG(3,(THIS_FILE, "...wake up.."));

-    }

-

-    return 0;

-}

-

-static int sleep_duration_test(void)

-{

-    enum { MIS = 20, DURATION = 1000, DURATION2 = 500 };

-    pj_status_t rc;

-

-    PJ_LOG(3,(THIS_FILE, "..running sleep duration test"));

-

-    /* Test pj_thread_sleep() and pj_gettimeofday() */

-    {

-        pj_time_val start, stop;

-	pj_uint32_t msec;

-

-        /* Mark start of test. */

-        rc = pj_gettimeofday(&start);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error: pj_gettimeofday()", rc);

-            return -10;

-        }

-

-        /* Sleep */

-        rc = pj_thread_sleep(DURATION);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error: pj_thread_sleep()", rc);

-            return -20;

-        }

-

-        /* Mark end of test. */

-        rc = pj_gettimeofday(&stop);

-

-        /* Calculate duration (store in stop). */

-        PJ_TIME_VAL_SUB(stop, start);

-

-	/* Convert to msec. */

-	msec = PJ_TIME_VAL_MSEC(stop);

-

-	/* Check if it's within range. */

-	if (msec < DURATION * (100-MIS)/100 ||

-	    msec > DURATION * (100+MIS)/100)

-	{

-	    PJ_LOG(3,(THIS_FILE, 

-		      "...error: slept for %d ms instead of %d ms "

-		      "(outside %d%% err window)",

-		      msec, DURATION, MIS));

-	    return -30;

-	}

-    }

-

-

-    /* Test pj_thread_sleep() and pj_get_timestamp() and friends */

-    {

-	pj_time_val t1, t2;

-        pj_timestamp start, stop;

-        pj_time_val elapsed;

-	pj_uint32_t msec;

-

-        /* Mark start of test. */

-        rc = pj_get_timestamp(&start);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error: pj_get_timestamp()", rc);

-            return -60;

-        }

-

-	/* ..also with gettimeofday() */

-	pj_gettimeofday(&t1);

-

-        /* Sleep */

-        rc = pj_thread_sleep(DURATION2);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error: pj_thread_sleep()", rc);

-            return -70;

-        }

-

-        /* Mark end of test. */

-        pj_get_timestamp(&stop);

-

-	/* ..also with gettimeofday() */

-	pj_gettimeofday(&t2);

-

-	/* Compare t1 and t2. */

-	if (PJ_TIME_VAL_LTE(t2, t1)) {

-	    PJ_LOG(3,(THIS_FILE, "...error: t2 is less than t1!!"));

-	    return -75;

-	}

-

-        /* Get elapsed time in time_val */

-        elapsed = pj_elapsed_time(&start, &stop);

-

-	msec = PJ_TIME_VAL_MSEC(elapsed);

-

-	/* Check if it's within range. */

-	if (msec < DURATION2 * (100-MIS)/100 ||

-	    msec > DURATION2 * (100+MIS)/100)

-	{

-	    PJ_LOG(3,(THIS_FILE, 

-		      "...error: slept for %d ms instead of %d ms "

-		      "(outside %d%% err window)",

-		      msec, DURATION2, MIS));

-	    return -30;

-	}

-    }

-

-    /* All done. */

-    return 0;

-}

-

-int sleep_test()

-{

-    int rc;

-

-    rc = simple_sleep_test();

-    if (rc != PJ_SUCCESS)

-	return rc;

-

-    rc = sleep_duration_test();

-    if (rc != PJ_SUCCESS)

-	return rc;

-

-    return 0;

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_sleep_test;

-#endif  /* INCLUDE_SLEEP_TEST */

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+/**
+ * \page page_pjlib_sleep_test Test: Sleep, Time, and Timestamp
+ *
+ * This file provides implementation of \b sleep_test().
+ *
+ * \section sleep_test_sec Scope of the Test
+ *
+ * This tests:
+ *  - whether pj_thread_sleep() works.
+ *  - whether pj_gettimeofday() works.
+ *  - whether pj_get_timestamp() and friends works.
+ *
+ * API tested:
+ *  - pj_thread_sleep()
+ *  - pj_gettimeofday()
+ *  - PJ_TIME_VAL_SUB()
+ *  - PJ_TIME_VAL_LTE()
+ *  - pj_get_timestamp()
+ *  - pj_get_timestamp_freq() (implicitly)
+ *  - pj_elapsed_time()
+ *  - pj_elapsed_usec()
+ *
+ *
+ * This file is <b>pjlib-test/sleep.c</b>
+ *
+ * \include pjlib-test/sleep.c
+ */
+
+#if INCLUDE_SLEEP_TEST
+
+#include <pjlib.h>
+
+#define THIS_FILE   "sleep_test"
+
+static int simple_sleep_test(void)
+{
+    enum { COUNT = 5 };
+    int i;
+    pj_status_t rc;
+    
+    PJ_LOG(3,(THIS_FILE, "..will write messages every 1 second:"));
+    
+    for (i=0; i<COUNT; ++i) {
+	rc = pj_thread_sleep(1000);
+	if (rc != PJ_SUCCESS) {
+	    app_perror("...error: pj_thread_sleep()", rc);
+	    return -10;
+	}
+	PJ_LOG(3,(THIS_FILE, "...wake up.."));
+    }
+
+    return 0;
+}
+
+static int sleep_duration_test(void)
+{
+    enum { MIS = 20, DURATION = 1000, DURATION2 = 500 };
+    pj_status_t rc;
+
+    PJ_LOG(3,(THIS_FILE, "..running sleep duration test"));
+
+    /* Test pj_thread_sleep() and pj_gettimeofday() */
+    {
+        pj_time_val start, stop;
+	pj_uint32_t msec;
+
+        /* Mark start of test. */
+        rc = pj_gettimeofday(&start);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error: pj_gettimeofday()", rc);
+            return -10;
+        }
+
+        /* Sleep */
+        rc = pj_thread_sleep(DURATION);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error: pj_thread_sleep()", rc);
+            return -20;
+        }
+
+        /* Mark end of test. */
+        rc = pj_gettimeofday(&stop);
+
+        /* Calculate duration (store in stop). */
+        PJ_TIME_VAL_SUB(stop, start);
+
+	/* Convert to msec. */
+	msec = PJ_TIME_VAL_MSEC(stop);
+
+	/* Check if it's within range. */
+	if (msec < DURATION * (100-MIS)/100 ||
+	    msec > DURATION * (100+MIS)/100)
+	{
+	    PJ_LOG(3,(THIS_FILE, 
+		      "...error: slept for %d ms instead of %d ms "
+		      "(outside %d%% err window)",
+		      msec, DURATION, MIS));
+	    return -30;
+	}
+    }
+
+
+    /* Test pj_thread_sleep() and pj_get_timestamp() and friends */
+    {
+	pj_time_val t1, t2;
+        pj_timestamp start, stop;
+        pj_time_val elapsed;
+	pj_uint32_t msec;
+
+        /* Mark start of test. */
+        rc = pj_get_timestamp(&start);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error: pj_get_timestamp()", rc);
+            return -60;
+        }
+
+	/* ..also with gettimeofday() */
+	pj_gettimeofday(&t1);
+
+        /* Sleep */
+        rc = pj_thread_sleep(DURATION2);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error: pj_thread_sleep()", rc);
+            return -70;
+        }
+
+        /* Mark end of test. */
+        pj_get_timestamp(&stop);
+
+	/* ..also with gettimeofday() */
+	pj_gettimeofday(&t2);
+
+	/* Compare t1 and t2. */
+	if (PJ_TIME_VAL_LTE(t2, t1)) {
+	    PJ_LOG(3,(THIS_FILE, "...error: t2 is less than t1!!"));
+	    return -75;
+	}
+
+        /* Get elapsed time in time_val */
+        elapsed = pj_elapsed_time(&start, &stop);
+
+	msec = PJ_TIME_VAL_MSEC(elapsed);
+
+	/* Check if it's within range. */
+	if (msec < DURATION2 * (100-MIS)/100 ||
+	    msec > DURATION2 * (100+MIS)/100)
+	{
+	    PJ_LOG(3,(THIS_FILE, 
+		      "...error: slept for %d ms instead of %d ms "
+		      "(outside %d%% err window)",
+		      msec, DURATION2, MIS));
+	    return -30;
+	}
+    }
+
+    /* All done. */
+    return 0;
+}
+
+int sleep_test()
+{
+    int rc;
+
+    rc = simple_sleep_test();
+    if (rc != PJ_SUCCESS)
+	return rc;
+
+    rc = sleep_duration_test();
+    if (rc != PJ_SUCCESS)
+	return rc;
+
+    return 0;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_sleep_test;
+#endif  /* INCLUDE_SLEEP_TEST */
diff --git a/pjlib/src/pjlib-test/sock.c b/pjlib/src/pjlib-test/sock.c
index 2961b78..b8af3cd 100644
--- a/pjlib/src/pjlib-test/sock.c
+++ b/pjlib/src/pjlib-test/sock.c
@@ -1,456 +1,456 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pjlib.h>

-#include "test.h"

-

-

-/**

- * \page page_pjlib_sock_test Test: Socket

- *

- * This file provides implementation of \b sock_test(). It tests the

- * various aspects of the socket API.

- *

- * \section sock_test_scope_sec Scope of the Test

- *

- * The scope of the test:

- *  - verify the validity of the address structs.

- *  - verify that address manipulation API works.

- *  - simple socket creation and destruction.

- *  - simple socket send/recv and sendto/recvfrom.

- *  - UDP connect()

- *  - send/recv big data.

- *  - all for both UDP and TCP.

- *

- * The APIs tested in this test:

- *  - pj_inet_aton()

- *  - pj_inet_ntoa()

- *  - pj_gethostname()

- *  - pj_sock_socket()

- *  - pj_sock_close()

- *  - pj_sock_send()

- *  - pj_sock_sendto()

- *  - pj_sock_recv()

- *  - pj_sock_recvfrom()

- *  - pj_sock_bind()

- *  - pj_sock_connect()

- *  - pj_sock_listen()

- *  - pj_sock_accept()

- *

- *

- * This file is <b>pjlib-test/sock.c</b>

- *

- * \include pjlib-test/sock.c

- */

-

-#if INCLUDE_SOCK_TEST

-

-#define UDP_PORT	51234

-#define TCP_PORT        (UDP_PORT+10)

-#define BIG_DATA_LEN	9000

-

-static char bigdata[BIG_DATA_LEN];

-static char bigbuffer[BIG_DATA_LEN];

-

-static int format_test(void)

-{

-    pj_str_t s = pj_str("127.0.0.1");

-    char *p;

-    pj_in_addr addr;

-    const pj_str_t *hostname;

-

-    PJ_LOG(3,("test", "...format_test()"));

-    

-    /* pj_inet_aton() */

-    if (pj_inet_aton(&s, &addr) != 1)

-	return -10;

-    

-    /* Check the result. */

-    p = (char*)&addr;

-    if (p[0]!=127 || p[1]!=0 || p[2]!=0 || p[3]!=1)

-	return -15;

-

-    /* pj_inet_ntoa() */

-    p = pj_inet_ntoa(addr);

-    if (!p)

-	return -20;

-

-    if (pj_strcmp2(&s, p) != 0)

-	return -30;

-

-    /* pj_gethostname() */

-    hostname = pj_gethostname();

-    if (!hostname || !hostname->ptr || !hostname->slen)

-	return -40;

-

-    /* pj_gethostaddr() */

-

-    return 0;

-}

-

-static int simple_sock_test(void)

-{

-    int types[2];

-    pj_sock_t sock;

-    int i;

-    pj_status_t rc = PJ_SUCCESS;

-

-    types[0] = PJ_SOCK_STREAM;

-    types[1] = PJ_SOCK_DGRAM;

-

-    PJ_LOG(3,("test", "...simple_sock_test()"));

-

-    for (i=0; i<sizeof(types)/sizeof(types[0]); ++i) {

-	

-	rc = pj_sock_socket(PJ_AF_INET, types[i], 0, &sock);

-	if (rc != PJ_SUCCESS) {

-	    app_perror("...error: unable to create socket type %d", rc);

-	    break;

-	} else {

-	    rc = pj_sock_close(sock);

-	    if (rc != 0) {

-		app_perror("...error: close socket", rc);

-		break;

-	    }

-	}

-    }

-    return rc;

-}

-

-

-static int send_recv_test(int sock_type,

-                          pj_sock_t ss, pj_sock_t cs,

-			  pj_sockaddr_in *dstaddr, pj_sockaddr_in *srcaddr, 

-			  int addrlen)

-{

-    enum { DATA_LEN = 16 };

-    char senddata[DATA_LEN+4], recvdata[DATA_LEN+4];

-    pj_ssize_t sent, received, total_received;

-    pj_status_t rc;

-

-    TRACE_(("test", "....create_random_string()"));

-    pj_create_random_string(senddata, DATA_LEN);

-    senddata[DATA_LEN-1] = '\0';

-

-    /*

-     * Test send/recv small data.

-     */

-    TRACE_(("test", "....sendto()"));

-    if (dstaddr) {

-        sent = DATA_LEN;

-	rc = pj_sock_sendto(cs, senddata, &sent, 0, dstaddr, addrlen);

-	if (rc != PJ_SUCCESS || sent != DATA_LEN) {

-	    app_perror("...sendto error", rc);

-	    rc = -140; goto on_error;

-	}

-    } else {

-        sent = DATA_LEN;

-	rc = pj_sock_send(cs, senddata, &sent, 0);

-	if (rc != PJ_SUCCESS || sent != DATA_LEN) {

-	    app_perror("...send error", rc);

-	    rc = -145; goto on_error;

-	}

-    }

-

-    TRACE_(("test", "....recv()"));

-    if (srcaddr) {

-	pj_sockaddr_in addr;

-	int srclen = sizeof(addr);

-	

-	pj_memset(&addr, 0, sizeof(addr));

-

-        received = DATA_LEN;

-	rc = pj_sock_recvfrom(ss, recvdata, &received, 0, &addr, &srclen);

-	if (rc != PJ_SUCCESS || received != DATA_LEN) {

-	    app_perror("...recvfrom error", rc);

-	    rc = -150; goto on_error;

-	}

-	if (srclen != addrlen)

-	    return -151;

-	if (pj_memcmp(&addr, srcaddr, srclen) != 0) {

-	    char srcaddr_str[32], addr_str[32];

-	    strcpy(srcaddr_str, pj_inet_ntoa(srcaddr->sin_addr));

-	    strcpy(addr_str, pj_inet_ntoa(addr.sin_addr));

-	    PJ_LOG(3,("test", "...error: src address mismatch (original=%s, "

-			      "recvfrom addr=%s)", 

-			      srcaddr_str, addr_str));

-	    return -152;

-	}

-	

-    } else {

-        /* Repeat recv() until all data is received.

-         * This applies only for non-UDP of course, since for UDP

-         * we would expect all data to be received in one packet.

-         */

-        total_received = 0;

-        do {

-            received = DATA_LEN-total_received;

-	    rc = pj_sock_recv(ss, recvdata+total_received, &received, 0);

-	    if (rc != PJ_SUCCESS) {

-	        app_perror("...recv error", rc);

-	        rc = -155; goto on_error;

-	    }

-            if (received <= 0) {

-                PJ_LOG(3,("", "...error: socket has closed! (received=%d)",

-                          received));

-                rc = -156; goto on_error;

-            }

-	    if (received != DATA_LEN-total_received) {

-                if (sock_type != PJ_SOCK_STREAM) {

-	            PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",

-                              DATA_LEN-total_received, received));

-	            rc = -157; goto on_error;

-                }

-	    }

-            total_received += received;

-        } while (total_received < DATA_LEN);

-    }

-

-    TRACE_(("test", "....memcmp()"));

-    if (pj_memcmp(senddata, recvdata, DATA_LEN) != 0) {

-	PJ_LOG(3,("","...error: received data mismatch "

-		     "(got:'%s' expecting:'%s'",

-		     recvdata, senddata));

-	rc = -160; goto on_error;

-    }

-

-    /*

-     * Test send/recv big data.

-     */

-    TRACE_(("test", "....sendto()"));

-    if (dstaddr) {

-        sent = BIG_DATA_LEN;

-	rc = pj_sock_sendto(cs, bigdata, &sent, 0, dstaddr, addrlen);

-	if (rc != PJ_SUCCESS || sent != BIG_DATA_LEN) {

-	    app_perror("...sendto error", rc);

-	    rc = -161; goto on_error;

-	}

-    } else {

-        sent = BIG_DATA_LEN;

-	rc = pj_sock_send(cs, bigdata, &sent, 0);

-	if (rc != PJ_SUCCESS || sent != BIG_DATA_LEN) {

-	    app_perror("...send error", rc);

-	    rc = -165; goto on_error;

-	}

-    }

-

-    TRACE_(("test", "....recv()"));

-

-    /* Repeat recv() until all data is received.

-     * This applies only for non-UDP of course, since for UDP

-     * we would expect all data to be received in one packet.

-     */

-    total_received = 0;

-    do {

-        received = BIG_DATA_LEN-total_received;

-	rc = pj_sock_recv(ss, bigbuffer+total_received, &received, 0);

-	if (rc != PJ_SUCCESS) {

-	    app_perror("...recv error", rc);

-	    rc = -170; goto on_error;

-	}

-        if (received <= 0) {

-            PJ_LOG(3,("", "...error: socket has closed! (received=%d)",

-                      received));

-            rc = -173; goto on_error;

-        }

-	if (received != BIG_DATA_LEN-total_received) {

-            if (sock_type != PJ_SOCK_STREAM) {

-	        PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",

-                          BIG_DATA_LEN-total_received, received));

-	        rc = -176; goto on_error;

-            }

-	}

-        total_received += received;

-    } while (total_received < BIG_DATA_LEN);

-

-    TRACE_(("test", "....memcmp()"));

-    if (pj_memcmp(bigdata, bigbuffer, BIG_DATA_LEN) != 0) {

-        PJ_LOG(3,("", "...error: received data has been altered!"));

-	rc = -180; goto on_error;

-    }

-    

-    rc = 0;

-

-on_error:

-    return rc;

-}

-

-static int udp_test(void)

-{

-    pj_sock_t cs = PJ_INVALID_SOCKET, ss = PJ_INVALID_SOCKET;

-    pj_sockaddr_in dstaddr, srcaddr;

-    pj_str_t s;

-    pj_status_t rc = 0, retval;

-

-    PJ_LOG(3,("test", "...udp_test()"));

-

-    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &ss);

-    if (rc != 0) {

-	app_perror("...error: unable to create socket", rc);

-	return -100;

-    }

-

-    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &cs);

-    if (rc != 0)

-	return -110;

-

-    /* Bind server socket. */

-    pj_memset(&dstaddr, 0, sizeof(dstaddr));

-    dstaddr.sin_family = PJ_AF_INET;

-    dstaddr.sin_port = pj_htons(UDP_PORT);

-    dstaddr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));

-    

-    if ((rc=pj_sock_bind(ss, &dstaddr, sizeof(dstaddr))) != 0) {

-	app_perror("...bind error", rc);

-	rc = -120; goto on_error;

-    }

-

-    /* Bind client socket. */

-    pj_memset(&srcaddr, 0, sizeof(srcaddr));

-    srcaddr.sin_family = PJ_AF_INET;

-    srcaddr.sin_port = pj_htons(UDP_PORT-1);

-    srcaddr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));

-

-    if ((rc=pj_sock_bind(cs, &srcaddr, sizeof(srcaddr))) != 0) {

-	app_perror("...bind error", rc);

-	rc = -121; goto on_error;

-    }

-	    

-    /* Test send/recv, with sendto */

-    rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, &dstaddr, NULL, 

-                        sizeof(dstaddr));

-    if (rc != 0)

-	goto on_error;

-

-    /* Test send/recv, with sendto and recvfrom */

-    rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, &dstaddr, 

-                        &srcaddr, sizeof(dstaddr));

-    if (rc != 0)

-	goto on_error;

-

-    /* connect() the sockets. */

-    rc = pj_sock_connect(cs, &dstaddr, sizeof(dstaddr));

-    if (rc != 0) {

-	app_perror("...connect() error", rc);

-	rc = -122; goto on_error;

-    }

-

-    /* Test send/recv with send() */

-    rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, NULL, NULL, 0);

-    if (rc != 0)

-	goto on_error;

-

-    /* Test send/recv with send() and recvfrom */

-    rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, NULL, &srcaddr, 

-                        sizeof(srcaddr));

-    if (rc != 0)

-	goto on_error;

-

-on_error:

-    retval = rc;

-    if (cs != PJ_INVALID_SOCKET) {

-        rc = pj_sock_close(cs);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error in closing socket", rc);

-            return -1000;

-        }

-    }

-    if (ss != PJ_INVALID_SOCKET) {

-        rc = pj_sock_close(ss);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...error in closing socket", rc);

-            return -1010;

-        }

-    }

-

-    return retval;

-}

-

-static int tcp_test(void)

-{

-    pj_sock_t cs, ss;

-    pj_status_t rc = 0, retval;

-

-    PJ_LOG(3,("test", "...tcp_test()"));

-

-    rc = app_socketpair(PJ_AF_INET, PJ_SOCK_STREAM, 0, &ss, &cs);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error: app_socketpair():", rc);

-        return -2000;

-    }

-

-    /* Test send/recv with send() and recv() */

-    retval = send_recv_test(PJ_SOCK_STREAM, ss, cs, NULL, NULL, 0);

-

-    rc = pj_sock_close(cs);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error in closing socket", rc);

-        return -2000;

-    }

-

-    rc = pj_sock_close(ss);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error in closing socket", rc);

-        return -2010;

-    }

-

-    return retval;

-}

-

-static int ioctl_test(void)

-{

-    return 0;

-}

-

-int sock_test()

-{

-    int rc;

-    

-    pj_create_random_string(bigdata, BIG_DATA_LEN);

-

-    rc = format_test();

-    if (rc != 0)

-	return rc;

-

-    rc = simple_sock_test();

-    if (rc != 0)

-	return rc;

-

-    rc = ioctl_test();

-    if (rc != 0)

-	return rc;

-

-    rc = udp_test();

-    if (rc != 0)

-	return rc;

-

-    rc = tcp_test();

-    if (rc != 0)

-	return rc;

-

-    return 0;

-}

-

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_sock_test;

-#endif	/* INCLUDE_SOCK_TEST */

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pjlib.h>
+#include "test.h"
+
+
+/**
+ * \page page_pjlib_sock_test Test: Socket
+ *
+ * This file provides implementation of \b sock_test(). It tests the
+ * various aspects of the socket API.
+ *
+ * \section sock_test_scope_sec Scope of the Test
+ *
+ * The scope of the test:
+ *  - verify the validity of the address structs.
+ *  - verify that address manipulation API works.
+ *  - simple socket creation and destruction.
+ *  - simple socket send/recv and sendto/recvfrom.
+ *  - UDP connect()
+ *  - send/recv big data.
+ *  - all for both UDP and TCP.
+ *
+ * The APIs tested in this test:
+ *  - pj_inet_aton()
+ *  - pj_inet_ntoa()
+ *  - pj_gethostname()
+ *  - pj_sock_socket()
+ *  - pj_sock_close()
+ *  - pj_sock_send()
+ *  - pj_sock_sendto()
+ *  - pj_sock_recv()
+ *  - pj_sock_recvfrom()
+ *  - pj_sock_bind()
+ *  - pj_sock_connect()
+ *  - pj_sock_listen()
+ *  - pj_sock_accept()
+ *
+ *
+ * This file is <b>pjlib-test/sock.c</b>
+ *
+ * \include pjlib-test/sock.c
+ */
+
+#if INCLUDE_SOCK_TEST
+
+#define UDP_PORT	51234
+#define TCP_PORT        (UDP_PORT+10)
+#define BIG_DATA_LEN	9000
+
+static char bigdata[BIG_DATA_LEN];
+static char bigbuffer[BIG_DATA_LEN];
+
+static int format_test(void)
+{
+    pj_str_t s = pj_str("127.0.0.1");
+    char *p;
+    pj_in_addr addr;
+    const pj_str_t *hostname;
+
+    PJ_LOG(3,("test", "...format_test()"));
+    
+    /* pj_inet_aton() */
+    if (pj_inet_aton(&s, &addr) != 1)
+	return -10;
+    
+    /* Check the result. */
+    p = (char*)&addr;
+    if (p[0]!=127 || p[1]!=0 || p[2]!=0 || p[3]!=1)
+	return -15;
+
+    /* pj_inet_ntoa() */
+    p = pj_inet_ntoa(addr);
+    if (!p)
+	return -20;
+
+    if (pj_strcmp2(&s, p) != 0)
+	return -30;
+
+    /* pj_gethostname() */
+    hostname = pj_gethostname();
+    if (!hostname || !hostname->ptr || !hostname->slen)
+	return -40;
+
+    /* pj_gethostaddr() */
+
+    return 0;
+}
+
+static int simple_sock_test(void)
+{
+    int types[2];
+    pj_sock_t sock;
+    int i;
+    pj_status_t rc = PJ_SUCCESS;
+
+    types[0] = PJ_SOCK_STREAM;
+    types[1] = PJ_SOCK_DGRAM;
+
+    PJ_LOG(3,("test", "...simple_sock_test()"));
+
+    for (i=0; i<sizeof(types)/sizeof(types[0]); ++i) {
+	
+	rc = pj_sock_socket(PJ_AF_INET, types[i], 0, &sock);
+	if (rc != PJ_SUCCESS) {
+	    app_perror("...error: unable to create socket type %d", rc);
+	    break;
+	} else {
+	    rc = pj_sock_close(sock);
+	    if (rc != 0) {
+		app_perror("...error: close socket", rc);
+		break;
+	    }
+	}
+    }
+    return rc;
+}
+
+
+static int send_recv_test(int sock_type,
+                          pj_sock_t ss, pj_sock_t cs,
+			  pj_sockaddr_in *dstaddr, pj_sockaddr_in *srcaddr, 
+			  int addrlen)
+{
+    enum { DATA_LEN = 16 };
+    char senddata[DATA_LEN+4], recvdata[DATA_LEN+4];
+    pj_ssize_t sent, received, total_received;
+    pj_status_t rc;
+
+    TRACE_(("test", "....create_random_string()"));
+    pj_create_random_string(senddata, DATA_LEN);
+    senddata[DATA_LEN-1] = '\0';
+
+    /*
+     * Test send/recv small data.
+     */
+    TRACE_(("test", "....sendto()"));
+    if (dstaddr) {
+        sent = DATA_LEN;
+	rc = pj_sock_sendto(cs, senddata, &sent, 0, dstaddr, addrlen);
+	if (rc != PJ_SUCCESS || sent != DATA_LEN) {
+	    app_perror("...sendto error", rc);
+	    rc = -140; goto on_error;
+	}
+    } else {
+        sent = DATA_LEN;
+	rc = pj_sock_send(cs, senddata, &sent, 0);
+	if (rc != PJ_SUCCESS || sent != DATA_LEN) {
+	    app_perror("...send error", rc);
+	    rc = -145; goto on_error;
+	}
+    }
+
+    TRACE_(("test", "....recv()"));
+    if (srcaddr) {
+	pj_sockaddr_in addr;
+	int srclen = sizeof(addr);
+	
+	pj_memset(&addr, 0, sizeof(addr));
+
+        received = DATA_LEN;
+	rc = pj_sock_recvfrom(ss, recvdata, &received, 0, &addr, &srclen);
+	if (rc != PJ_SUCCESS || received != DATA_LEN) {
+	    app_perror("...recvfrom error", rc);
+	    rc = -150; goto on_error;
+	}
+	if (srclen != addrlen)
+	    return -151;
+	if (pj_memcmp(&addr, srcaddr, srclen) != 0) {
+	    char srcaddr_str[32], addr_str[32];
+	    strcpy(srcaddr_str, pj_inet_ntoa(srcaddr->sin_addr));
+	    strcpy(addr_str, pj_inet_ntoa(addr.sin_addr));
+	    PJ_LOG(3,("test", "...error: src address mismatch (original=%s, "
+			      "recvfrom addr=%s)", 
+			      srcaddr_str, addr_str));
+	    return -152;
+	}
+	
+    } else {
+        /* Repeat recv() until all data is received.
+         * This applies only for non-UDP of course, since for UDP
+         * we would expect all data to be received in one packet.
+         */
+        total_received = 0;
+        do {
+            received = DATA_LEN-total_received;
+	    rc = pj_sock_recv(ss, recvdata+total_received, &received, 0);
+	    if (rc != PJ_SUCCESS) {
+	        app_perror("...recv error", rc);
+	        rc = -155; goto on_error;
+	    }
+            if (received <= 0) {
+                PJ_LOG(3,("", "...error: socket has closed! (received=%d)",
+                          received));
+                rc = -156; goto on_error;
+            }
+	    if (received != DATA_LEN-total_received) {
+                if (sock_type != PJ_SOCK_STREAM) {
+	            PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",
+                              DATA_LEN-total_received, received));
+	            rc = -157; goto on_error;
+                }
+	    }
+            total_received += received;
+        } while (total_received < DATA_LEN);
+    }
+
+    TRACE_(("test", "....memcmp()"));
+    if (pj_memcmp(senddata, recvdata, DATA_LEN) != 0) {
+	PJ_LOG(3,("","...error: received data mismatch "
+		     "(got:'%s' expecting:'%s'",
+		     recvdata, senddata));
+	rc = -160; goto on_error;
+    }
+
+    /*
+     * Test send/recv big data.
+     */
+    TRACE_(("test", "....sendto()"));
+    if (dstaddr) {
+        sent = BIG_DATA_LEN;
+	rc = pj_sock_sendto(cs, bigdata, &sent, 0, dstaddr, addrlen);
+	if (rc != PJ_SUCCESS || sent != BIG_DATA_LEN) {
+	    app_perror("...sendto error", rc);
+	    rc = -161; goto on_error;
+	}
+    } else {
+        sent = BIG_DATA_LEN;
+	rc = pj_sock_send(cs, bigdata, &sent, 0);
+	if (rc != PJ_SUCCESS || sent != BIG_DATA_LEN) {
+	    app_perror("...send error", rc);
+	    rc = -165; goto on_error;
+	}
+    }
+
+    TRACE_(("test", "....recv()"));
+
+    /* Repeat recv() until all data is received.
+     * This applies only for non-UDP of course, since for UDP
+     * we would expect all data to be received in one packet.
+     */
+    total_received = 0;
+    do {
+        received = BIG_DATA_LEN-total_received;
+	rc = pj_sock_recv(ss, bigbuffer+total_received, &received, 0);
+	if (rc != PJ_SUCCESS) {
+	    app_perror("...recv error", rc);
+	    rc = -170; goto on_error;
+	}
+        if (received <= 0) {
+            PJ_LOG(3,("", "...error: socket has closed! (received=%d)",
+                      received));
+            rc = -173; goto on_error;
+        }
+	if (received != BIG_DATA_LEN-total_received) {
+            if (sock_type != PJ_SOCK_STREAM) {
+	        PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",
+                          BIG_DATA_LEN-total_received, received));
+	        rc = -176; goto on_error;
+            }
+	}
+        total_received += received;
+    } while (total_received < BIG_DATA_LEN);
+
+    TRACE_(("test", "....memcmp()"));
+    if (pj_memcmp(bigdata, bigbuffer, BIG_DATA_LEN) != 0) {
+        PJ_LOG(3,("", "...error: received data has been altered!"));
+	rc = -180; goto on_error;
+    }
+    
+    rc = 0;
+
+on_error:
+    return rc;
+}
+
+static int udp_test(void)
+{
+    pj_sock_t cs = PJ_INVALID_SOCKET, ss = PJ_INVALID_SOCKET;
+    pj_sockaddr_in dstaddr, srcaddr;
+    pj_str_t s;
+    pj_status_t rc = 0, retval;
+
+    PJ_LOG(3,("test", "...udp_test()"));
+
+    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &ss);
+    if (rc != 0) {
+	app_perror("...error: unable to create socket", rc);
+	return -100;
+    }
+
+    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &cs);
+    if (rc != 0)
+	return -110;
+
+    /* Bind server socket. */
+    pj_memset(&dstaddr, 0, sizeof(dstaddr));
+    dstaddr.sin_family = PJ_AF_INET;
+    dstaddr.sin_port = pj_htons(UDP_PORT);
+    dstaddr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));
+    
+    if ((rc=pj_sock_bind(ss, &dstaddr, sizeof(dstaddr))) != 0) {
+	app_perror("...bind error", rc);
+	rc = -120; goto on_error;
+    }
+
+    /* Bind client socket. */
+    pj_memset(&srcaddr, 0, sizeof(srcaddr));
+    srcaddr.sin_family = PJ_AF_INET;
+    srcaddr.sin_port = pj_htons(UDP_PORT-1);
+    srcaddr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));
+
+    if ((rc=pj_sock_bind(cs, &srcaddr, sizeof(srcaddr))) != 0) {
+	app_perror("...bind error", rc);
+	rc = -121; goto on_error;
+    }
+	    
+    /* Test send/recv, with sendto */
+    rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, &dstaddr, NULL, 
+                        sizeof(dstaddr));
+    if (rc != 0)
+	goto on_error;
+
+    /* Test send/recv, with sendto and recvfrom */
+    rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, &dstaddr, 
+                        &srcaddr, sizeof(dstaddr));
+    if (rc != 0)
+	goto on_error;
+
+    /* connect() the sockets. */
+    rc = pj_sock_connect(cs, &dstaddr, sizeof(dstaddr));
+    if (rc != 0) {
+	app_perror("...connect() error", rc);
+	rc = -122; goto on_error;
+    }
+
+    /* Test send/recv with send() */
+    rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, NULL, NULL, 0);
+    if (rc != 0)
+	goto on_error;
+
+    /* Test send/recv with send() and recvfrom */
+    rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, NULL, &srcaddr, 
+                        sizeof(srcaddr));
+    if (rc != 0)
+	goto on_error;
+
+on_error:
+    retval = rc;
+    if (cs != PJ_INVALID_SOCKET) {
+        rc = pj_sock_close(cs);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error in closing socket", rc);
+            return -1000;
+        }
+    }
+    if (ss != PJ_INVALID_SOCKET) {
+        rc = pj_sock_close(ss);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...error in closing socket", rc);
+            return -1010;
+        }
+    }
+
+    return retval;
+}
+
+static int tcp_test(void)
+{
+    pj_sock_t cs, ss;
+    pj_status_t rc = 0, retval;
+
+    PJ_LOG(3,("test", "...tcp_test()"));
+
+    rc = app_socketpair(PJ_AF_INET, PJ_SOCK_STREAM, 0, &ss, &cs);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error: app_socketpair():", rc);
+        return -2000;
+    }
+
+    /* Test send/recv with send() and recv() */
+    retval = send_recv_test(PJ_SOCK_STREAM, ss, cs, NULL, NULL, 0);
+
+    rc = pj_sock_close(cs);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error in closing socket", rc);
+        return -2000;
+    }
+
+    rc = pj_sock_close(ss);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error in closing socket", rc);
+        return -2010;
+    }
+
+    return retval;
+}
+
+static int ioctl_test(void)
+{
+    return 0;
+}
+
+int sock_test()
+{
+    int rc;
+    
+    pj_create_random_string(bigdata, BIG_DATA_LEN);
+
+    rc = format_test();
+    if (rc != 0)
+	return rc;
+
+    rc = simple_sock_test();
+    if (rc != 0)
+	return rc;
+
+    rc = ioctl_test();
+    if (rc != 0)
+	return rc;
+
+    rc = udp_test();
+    if (rc != 0)
+	return rc;
+
+    rc = tcp_test();
+    if (rc != 0)
+	return rc;
+
+    return 0;
+}
+
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_sock_test;
+#endif	/* INCLUDE_SOCK_TEST */
+
diff --git a/pjlib/src/pjlib-test/sock_perf.c b/pjlib/src/pjlib-test/sock_perf.c
index bb20f8a..a3b46b9 100644
--- a/pjlib/src/pjlib-test/sock_perf.c
+++ b/pjlib/src/pjlib-test/sock_perf.c
@@ -1,183 +1,183 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pjlib.h>

-#include <pj/compat/high_precision.h>

-

-

-/**

- * \page page_pjlib_sock_perf_test Test: Socket Performance

- *

- * Test the performance of the socket communication. This will perform

- * simple producer-consumer type of test, where we calculate how long

- * does it take to send certain number of packets from producer to

- * consumer.

- *

- * This file is <b>pjlib-test/sock_perf.c</b>

- *

- * \include pjlib-test/sock_perf.c

- */

-

-#if INCLUDE_SOCK_PERF_TEST

-

-/*

- * sock_producer_consumer()

- *

- * Simple producer-consumer benchmarking. Send loop number of

- * buf_size size packets as fast as possible.

- */

-static int sock_producer_consumer(int sock_type,

-                                  unsigned buf_size,

-                                  unsigned loop, 

-                                  unsigned *p_bandwidth)

-{

-    pj_sock_t consumer, producer;

-    pj_pool_t *pool;

-    char *outgoing_buffer, *incoming_buffer;

-    pj_timestamp start, stop;

-    unsigned i;

-    pj_highprec_t elapsed, bandwidth;

-    pj_size_t total_received;

-    pj_status_t rc;

-

-    /* Create pool. */

-    pool = pj_pool_create(mem, NULL, 4096, 4096, NULL);

-    if (!pool)

-        return -10;

-

-    /* Create producer-consumer pair. */

-    rc = app_socketpair(PJ_AF_INET, sock_type, 0, &consumer, &producer);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error: create socket pair", rc);

-        return -20;

-    }

-

-    /* Create buffers. */

-    outgoing_buffer = pj_pool_alloc(pool, buf_size);

-    incoming_buffer = pj_pool_alloc(pool, buf_size);

-

-    /* Start loop. */

-    pj_get_timestamp(&start);

-    total_received = 0;

-    for (i=0; i<loop; ++i) {

-        pj_ssize_t sent, part_received, received;

-	pj_time_val delay;

-

-        sent = buf_size;

-        rc = pj_sock_send(producer, outgoing_buffer, &sent, 0);

-        if (rc != PJ_SUCCESS || sent != (pj_ssize_t)buf_size) {

-            app_perror("...error: send()", rc);

-            return -61;

-        }

-

-        /* Repeat recv() until all data is part_received.

-         * This applies only for non-UDP of course, since for UDP

-         * we would expect all data to be part_received in one packet.

-         */

-        received = 0;

-        do {

-            part_received = buf_size-received;

-	    rc = pj_sock_recv(consumer, incoming_buffer+received, 

-			      &part_received, 0);

-	    if (rc != PJ_SUCCESS) {

-	        app_perror("...recv error", rc);

-	        return -70;

-	    }

-            if (part_received <= 0) {

-                PJ_LOG(3,("", "...error: socket has closed (part_received=%d)!",

-                          part_received));

-                return -73;

-            }

-	    if ((pj_size_t)part_received != buf_size-received) {

-                if (sock_type != PJ_SOCK_STREAM) {

-	            PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",

-                              buf_size-received, part_received));

-	            return -76;

-                }

-	    }

-            received += part_received;

-        } while ((pj_size_t)received < buf_size);

-

-	total_received += received;

-

-	/* Stop test if it's been runnign for more than 10 secs. */

-	pj_get_timestamp(&stop);

-	delay = pj_elapsed_time(&start, &stop);

-	if (delay.sec > 10)

-	    break;

-    }

-

-    /* Stop timer. */

-    pj_get_timestamp(&stop);

-

-    elapsed = pj_elapsed_usec(&start, &stop);

-

-    /* bandwidth = total_received * 1000 / elapsed */

-    bandwidth = total_received;

-    pj_highprec_mul(bandwidth, 1000);

-    pj_highprec_div(bandwidth, elapsed);

-    

-    *p_bandwidth = (pj_uint32_t)bandwidth;

-

-    /* Close sockets. */

-    pj_sock_close(consumer);

-    pj_sock_close(producer);

-

-    /* Done */

-    pj_pool_release(pool);

-

-    return 0;

-}

-

-/*

- * sock_perf_test()

- *

- * Main test entry.

- */

-int sock_perf_test(void)

-{

-    enum { LOOP = 64 * 1024 };

-    int rc;

-    unsigned bandwidth;

-

-    PJ_LOG(3,("", "...benchmarking socket "

-                  "(2 sockets, packet=512, single threaded):"));

-    

-    /* Benchmarking UDP */

-    rc = sock_producer_consumer(PJ_SOCK_DGRAM, 512, LOOP, &bandwidth);

-    if (rc != 0) return rc;

-    PJ_LOG(3,("", "....bandwidth UDP = %d KB/s", bandwidth));

-

-    /* Benchmarking TCP */

-    rc = sock_producer_consumer(PJ_SOCK_STREAM, 512, LOOP, &bandwidth);

-    if (rc != 0) return rc;

-    PJ_LOG(3,("", "....bandwidth TCP = %d KB/s", bandwidth));

-

-    return rc;

-}

-

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_sock_perf_test;

-#endif  /* INCLUDE_SOCK_PERF_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib.h>
+#include <pj/compat/high_precision.h>
+
+
+/**
+ * \page page_pjlib_sock_perf_test Test: Socket Performance
+ *
+ * Test the performance of the socket communication. This will perform
+ * simple producer-consumer type of test, where we calculate how long
+ * does it take to send certain number of packets from producer to
+ * consumer.
+ *
+ * This file is <b>pjlib-test/sock_perf.c</b>
+ *
+ * \include pjlib-test/sock_perf.c
+ */
+
+#if INCLUDE_SOCK_PERF_TEST
+
+/*
+ * sock_producer_consumer()
+ *
+ * Simple producer-consumer benchmarking. Send loop number of
+ * buf_size size packets as fast as possible.
+ */
+static int sock_producer_consumer(int sock_type,
+                                  unsigned buf_size,
+                                  unsigned loop, 
+                                  unsigned *p_bandwidth)
+{
+    pj_sock_t consumer, producer;
+    pj_pool_t *pool;
+    char *outgoing_buffer, *incoming_buffer;
+    pj_timestamp start, stop;
+    unsigned i;
+    pj_highprec_t elapsed, bandwidth;
+    pj_size_t total_received;
+    pj_status_t rc;
+
+    /* Create pool. */
+    pool = pj_pool_create(mem, NULL, 4096, 4096, NULL);
+    if (!pool)
+        return -10;
+
+    /* Create producer-consumer pair. */
+    rc = app_socketpair(PJ_AF_INET, sock_type, 0, &consumer, &producer);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error: create socket pair", rc);
+        return -20;
+    }
+
+    /* Create buffers. */
+    outgoing_buffer = pj_pool_alloc(pool, buf_size);
+    incoming_buffer = pj_pool_alloc(pool, buf_size);
+
+    /* Start loop. */
+    pj_get_timestamp(&start);
+    total_received = 0;
+    for (i=0; i<loop; ++i) {
+        pj_ssize_t sent, part_received, received;
+	pj_time_val delay;
+
+        sent = buf_size;
+        rc = pj_sock_send(producer, outgoing_buffer, &sent, 0);
+        if (rc != PJ_SUCCESS || sent != (pj_ssize_t)buf_size) {
+            app_perror("...error: send()", rc);
+            return -61;
+        }
+
+        /* Repeat recv() until all data is part_received.
+         * This applies only for non-UDP of course, since for UDP
+         * we would expect all data to be part_received in one packet.
+         */
+        received = 0;
+        do {
+            part_received = buf_size-received;
+	    rc = pj_sock_recv(consumer, incoming_buffer+received, 
+			      &part_received, 0);
+	    if (rc != PJ_SUCCESS) {
+	        app_perror("...recv error", rc);
+	        return -70;
+	    }
+            if (part_received <= 0) {
+                PJ_LOG(3,("", "...error: socket has closed (part_received=%d)!",
+                          part_received));
+                return -73;
+            }
+	    if ((pj_size_t)part_received != buf_size-received) {
+                if (sock_type != PJ_SOCK_STREAM) {
+	            PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",
+                              buf_size-received, part_received));
+	            return -76;
+                }
+	    }
+            received += part_received;
+        } while ((pj_size_t)received < buf_size);
+
+	total_received += received;
+
+	/* Stop test if it's been runnign for more than 10 secs. */
+	pj_get_timestamp(&stop);
+	delay = pj_elapsed_time(&start, &stop);
+	if (delay.sec > 10)
+	    break;
+    }
+
+    /* Stop timer. */
+    pj_get_timestamp(&stop);
+
+    elapsed = pj_elapsed_usec(&start, &stop);
+
+    /* bandwidth = total_received * 1000 / elapsed */
+    bandwidth = total_received;
+    pj_highprec_mul(bandwidth, 1000);
+    pj_highprec_div(bandwidth, elapsed);
+    
+    *p_bandwidth = (pj_uint32_t)bandwidth;
+
+    /* Close sockets. */
+    pj_sock_close(consumer);
+    pj_sock_close(producer);
+
+    /* Done */
+    pj_pool_release(pool);
+
+    return 0;
+}
+
+/*
+ * sock_perf_test()
+ *
+ * Main test entry.
+ */
+int sock_perf_test(void)
+{
+    enum { LOOP = 64 * 1024 };
+    int rc;
+    unsigned bandwidth;
+
+    PJ_LOG(3,("", "...benchmarking socket "
+                  "(2 sockets, packet=512, single threaded):"));
+    
+    /* Benchmarking UDP */
+    rc = sock_producer_consumer(PJ_SOCK_DGRAM, 512, LOOP, &bandwidth);
+    if (rc != 0) return rc;
+    PJ_LOG(3,("", "....bandwidth UDP = %d KB/s", bandwidth));
+
+    /* Benchmarking TCP */
+    rc = sock_producer_consumer(PJ_SOCK_STREAM, 512, LOOP, &bandwidth);
+    if (rc != 0) return rc;
+    PJ_LOG(3,("", "....bandwidth TCP = %d KB/s", bandwidth));
+
+    return rc;
+}
+
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_sock_perf_test;
+#endif  /* INCLUDE_SOCK_PERF_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/string.c b/pjlib/src/pjlib-test/string.c
index 7199c56..96a4ade 100644
--- a/pjlib/src/pjlib-test/string.c
+++ b/pjlib/src/pjlib-test/string.c
@@ -1,174 +1,174 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pj/string.h>

-#include <pj/pool.h>

-#include <pj/log.h>

-#include "test.h"

-

-/**

- * \page page_pjlib_string_test Test: String

- *

- * This file provides implementation of \b string_test(). It tests the

- * functionality of the string API.

- *

- * \section sleep_test_sec Scope of the Test

- *

- * API tested:

- *  - pj_str()

- *  - pj_strcmp()

- *  - pj_strcmp2()

- *  - pj_stricmp()

- *  - pj_strlen()

- *  - pj_strncmp()

- *  - pj_strnicmp()

- *  - pj_strchr()

- *  - pj_strdup()

- *  - pj_strdup2()

- *  - pj_strcpy()

- *  - pj_strcat()

- *  - pj_strtrim()

- *  - pj_utoa()

- *  - pj_strtoul()

- *  - pj_create_random_string()

- *

- *

- * This file is <b>pjlib-test/string.c</b>

- *

- * \include pjlib-test/string.c

- */

-

-#if INCLUDE_STRING_TEST

-

-#ifdef _MSC_VER

-#   pragma warning(disable: 4204)

-#endif

-

-#define HELLO_WORLD	"Hello World"

-#define JUST_HELLO	"Hello"

-#define UL_VALUE	3456789012UL

-

-int string_test(void)

-{

-    const pj_str_t hello_world = { HELLO_WORLD, strlen(HELLO_WORLD) };

-    const pj_str_t just_hello = { JUST_HELLO, strlen(JUST_HELLO) };

-    pj_str_t s1, s2, s3, s4, s5;

-    enum { RCOUNT = 10, RLEN = 16 };

-    pj_str_t random[RCOUNT];

-    pj_pool_t *pool;

-    int i;

-

-    pool = pj_pool_create(mem, NULL, 4096, 0, NULL);

-    if (!pool) return -5;

-    

-    /* 

-     * pj_str(), pj_strcmp(), pj_stricmp(), pj_strlen(), 

-     * pj_strncmp(), pj_strchr() 

-     */

-    s1 = pj_str(HELLO_WORLD);

-    if (pj_strcmp(&s1, &hello_world) != 0)

-	return -10;

-    if (pj_stricmp(&s1, &hello_world) != 0)

-	return -20;

-    if (pj_strcmp(&s1, &just_hello) <= 0)

-	return -30;

-    if (pj_stricmp(&s1, &just_hello) <= 0)

-	return -40;

-    if (pj_strlen(&s1) != strlen(HELLO_WORLD))

-	return -50;

-    if (pj_strncmp(&s1, &hello_world, 5) != 0)

-	return -60;

-    if (pj_strnicmp(&s1, &hello_world, 5) != 0)

-	return -70;

-    if (pj_strchr(&s1, HELLO_WORLD[1]) != s1.ptr+1)

-	return -80;

-

-    /* 

-     * pj_strdup() 

-     */

-    if (!pj_strdup(pool, &s2, &s1))

-	return -100;

-    if (pj_strcmp(&s1, &s2) != 0)

-	return -110;

-    

-    /* 

-     * pj_strcpy(), pj_strcat() 

-     */

-    s3.ptr = pj_pool_alloc(pool, 256);

-    if (!s3.ptr) 

-	return -200;

-    pj_strcpy(&s3, &s2);

-    pj_strcat(&s3, &just_hello);

-

-    if (pj_strcmp2(&s3, HELLO_WORLD JUST_HELLO) != 0)

-	return -210;

-

-    /* 

-     * pj_strdup2(), pj_strtrim(). 

-     */

-    pj_strdup2(pool, &s4, " " HELLO_WORLD "\t ");

-    pj_strtrim(&s4);

-    if (pj_strcmp2(&s4, HELLO_WORLD) != 0)

-	return -250;

-

-    /* 

-     * pj_utoa() 

-     */

-    s5.ptr = pj_pool_alloc(pool, 16);

-    if (!s5.ptr)

-	return -270;

-    s5.slen = pj_utoa(UL_VALUE, s5.ptr);

-

-    /* 

-     * pj_strtoul() 

-     */

-    if (pj_strtoul(&s5) != UL_VALUE)

-	return -280;

-

-    /* 

-     * pj_create_random_string() 

-     * Check that no duplicate strings are returned.

-     */

-    for (i=0; i<RCOUNT; ++i) {

-	int j;

-	

-	random[i].ptr = pj_pool_alloc(pool, RLEN);

-	if (!random[i].ptr)

-	    return -320;

-

-        random[i].slen = RLEN;

-	pj_create_random_string(random[i].ptr, RLEN);

-

-	for (j=0; j<i; ++j) {

-	    if (pj_strcmp(&random[i], &random[j])==0)

-		return -330;

-	}

-    }

-

-    /* Done. */

-    pj_pool_release(pool);

-    return 0;

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_string_test;

-#endif	/* INCLUDE_STRING_TEST */

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/string.h>
+#include <pj/pool.h>
+#include <pj/log.h>
+#include "test.h"
+
+/**
+ * \page page_pjlib_string_test Test: String
+ *
+ * This file provides implementation of \b string_test(). It tests the
+ * functionality of the string API.
+ *
+ * \section sleep_test_sec Scope of the Test
+ *
+ * API tested:
+ *  - pj_str()
+ *  - pj_strcmp()
+ *  - pj_strcmp2()
+ *  - pj_stricmp()
+ *  - pj_strlen()
+ *  - pj_strncmp()
+ *  - pj_strnicmp()
+ *  - pj_strchr()
+ *  - pj_strdup()
+ *  - pj_strdup2()
+ *  - pj_strcpy()
+ *  - pj_strcat()
+ *  - pj_strtrim()
+ *  - pj_utoa()
+ *  - pj_strtoul()
+ *  - pj_create_random_string()
+ *
+ *
+ * This file is <b>pjlib-test/string.c</b>
+ *
+ * \include pjlib-test/string.c
+ */
+
+#if INCLUDE_STRING_TEST
+
+#ifdef _MSC_VER
+#   pragma warning(disable: 4204)
+#endif
+
+#define HELLO_WORLD	"Hello World"
+#define JUST_HELLO	"Hello"
+#define UL_VALUE	3456789012UL
+
+int string_test(void)
+{
+    const pj_str_t hello_world = { HELLO_WORLD, strlen(HELLO_WORLD) };
+    const pj_str_t just_hello = { JUST_HELLO, strlen(JUST_HELLO) };
+    pj_str_t s1, s2, s3, s4, s5;
+    enum { RCOUNT = 10, RLEN = 16 };
+    pj_str_t random[RCOUNT];
+    pj_pool_t *pool;
+    int i;
+
+    pool = pj_pool_create(mem, NULL, 4096, 0, NULL);
+    if (!pool) return -5;
+    
+    /* 
+     * pj_str(), pj_strcmp(), pj_stricmp(), pj_strlen(), 
+     * pj_strncmp(), pj_strchr() 
+     */
+    s1 = pj_str(HELLO_WORLD);
+    if (pj_strcmp(&s1, &hello_world) != 0)
+	return -10;
+    if (pj_stricmp(&s1, &hello_world) != 0)
+	return -20;
+    if (pj_strcmp(&s1, &just_hello) <= 0)
+	return -30;
+    if (pj_stricmp(&s1, &just_hello) <= 0)
+	return -40;
+    if (pj_strlen(&s1) != strlen(HELLO_WORLD))
+	return -50;
+    if (pj_strncmp(&s1, &hello_world, 5) != 0)
+	return -60;
+    if (pj_strnicmp(&s1, &hello_world, 5) != 0)
+	return -70;
+    if (pj_strchr(&s1, HELLO_WORLD[1]) != s1.ptr+1)
+	return -80;
+
+    /* 
+     * pj_strdup() 
+     */
+    if (!pj_strdup(pool, &s2, &s1))
+	return -100;
+    if (pj_strcmp(&s1, &s2) != 0)
+	return -110;
+    
+    /* 
+     * pj_strcpy(), pj_strcat() 
+     */
+    s3.ptr = pj_pool_alloc(pool, 256);
+    if (!s3.ptr) 
+	return -200;
+    pj_strcpy(&s3, &s2);
+    pj_strcat(&s3, &just_hello);
+
+    if (pj_strcmp2(&s3, HELLO_WORLD JUST_HELLO) != 0)
+	return -210;
+
+    /* 
+     * pj_strdup2(), pj_strtrim(). 
+     */
+    pj_strdup2(pool, &s4, " " HELLO_WORLD "\t ");
+    pj_strtrim(&s4);
+    if (pj_strcmp2(&s4, HELLO_WORLD) != 0)
+	return -250;
+
+    /* 
+     * pj_utoa() 
+     */
+    s5.ptr = pj_pool_alloc(pool, 16);
+    if (!s5.ptr)
+	return -270;
+    s5.slen = pj_utoa(UL_VALUE, s5.ptr);
+
+    /* 
+     * pj_strtoul() 
+     */
+    if (pj_strtoul(&s5) != UL_VALUE)
+	return -280;
+
+    /* 
+     * pj_create_random_string() 
+     * Check that no duplicate strings are returned.
+     */
+    for (i=0; i<RCOUNT; ++i) {
+	int j;
+	
+	random[i].ptr = pj_pool_alloc(pool, RLEN);
+	if (!random[i].ptr)
+	    return -320;
+
+        random[i].slen = RLEN;
+	pj_create_random_string(random[i].ptr, RLEN);
+
+	for (j=0; j<i; ++j) {
+	    if (pj_strcmp(&random[i], &random[j])==0)
+		return -330;
+	}
+    }
+
+    /* Done. */
+    pj_pool_release(pool);
+    return 0;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_string_test;
+#endif	/* INCLUDE_STRING_TEST */
+
diff --git a/pjlib/src/pjlib-test/test.c b/pjlib/src/pjlib-test/test.c
index 5fb89af..6a1342c 100644
--- a/pjlib/src/pjlib-test/test.c
+++ b/pjlib/src/pjlib-test/test.c
@@ -1,199 +1,199 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pjlib.h>

-#ifdef _MSC_VER

-#  pragma warning(disable:4127)

-#endif

-

-#define DO_TEST(test)	do { \

-			    PJ_LOG(3, ("test", "Running %s...", #test));  \

-			    rc = test; \

-			    PJ_LOG(3, ("test",  \

-				       "%s(%d)",  \

-				       (rc ? "..ERROR" : "..success"), rc)); \

-			    if (rc!=0) goto on_return; \

-			} while (0)

-

-

-pj_pool_factory *mem;

-

-int param_echo_sock_type;

-const char *param_echo_server = ECHO_SERVER_ADDRESS;

-int param_echo_port = ECHO_SERVER_START_PORT;

-

-int test_inner(void)

-{

-    pj_caching_pool caching_pool;

-    const char *filename;

-    int line;

-    int rc = 0;

-

-    mem = &caching_pool.factory;

-

-    pj_log_set_level(3);

-    pj_log_set_decor(PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | 

-                     PJ_LOG_HAS_MICRO_SEC);

-

-    rc = pj_init();

-    if (rc != 0) {

-	app_perror("pj_init() error!!", rc);

-	return rc;

-    }

-    

-    pj_dump_config();

-    pj_caching_pool_init( &caching_pool, &pj_pool_factory_default_policy, 0 );

-

-#if INCLUDE_ERRNO_TEST

-    DO_TEST( errno_test() );

-#endif

-

-#if INCLUDE_TIMESTAMP_TEST

-    DO_TEST( timestamp_test() );

-#endif

-

-#if INCLUDE_EXCEPTION_TEST

-    DO_TEST( exception_test() );

-#endif

-

-#if INCLUDE_RAND_TEST

-    DO_TEST( rand_test() );

-#endif

-

-#if INCLUDE_LIST_TEST

-    DO_TEST( list_test() );

-#endif

-

-#if INCLUDE_POOL_TEST

-    DO_TEST( pool_test() );

-#endif

-

-#if INCLUDE_POOL_PERF_TEST

-    DO_TEST( pool_perf_test() );

-#endif

-

-#if INCLUDE_STRING_TEST

-    DO_TEST( string_test() );

-#endif

-    

-#if INCLUDE_FIFOBUF_TEST

-    DO_TEST( fifobuf_test() );

-#endif

-

-#if INCLUDE_RBTREE_TEST

-    DO_TEST( rbtree_test() );

-#endif

-

-#if INCLUDE_ATOMIC_TEST

-    DO_TEST( atomic_test() );

-#endif

-

-#if INCLUDE_MUTEX_TEST

-    DO_TEST( mutex_test() );

-#endif

-

-#if INCLUDE_TIMER_TEST

-    DO_TEST( timer_test() );

-#endif

-

-#if INCLUDE_SLEEP_TEST

-    DO_TEST( sleep_test() );

-#endif

-

-#if INCLUDE_THREAD_TEST

-    DO_TEST( thread_test() );

-#endif

-

-#if INCLUDE_SOCK_TEST

-    DO_TEST( sock_test() );

-#endif

-

-#if INCLUDE_SOCK_PERF_TEST

-    DO_TEST( sock_perf_test() );

-#endif

-

-#if INCLUDE_SELECT_TEST

-    DO_TEST( select_test() );

-#endif

-

-#if INCLUDE_UDP_IOQUEUE_TEST

-    DO_TEST( udp_ioqueue_test() );

-#endif

-

-#if PJ_HAS_TCP && INCLUDE_TCP_IOQUEUE_TEST

-    DO_TEST( tcp_ioqueue_test() );

-#endif

-

-#if INCLUDE_IOQUEUE_PERF_TEST

-    DO_TEST( ioqueue_perf_test() );

-#endif

-

-#if INCLUDE_FILE_TEST

-    DO_TEST( file_test() );

-#endif

-

-#if INCLUDE_ECHO_SERVER

-    //echo_server();

-    //echo_srv_sync();

-    udp_echo_srv_ioqueue();

-

-#elif INCLUDE_ECHO_CLIENT

-    if (param_echo_sock_type == 0)

-        param_echo_sock_type = PJ_SOCK_DGRAM;

-

-    echo_client( param_echo_sock_type, 

-                 param_echo_server, 

-                 param_echo_port);

-#endif

-

-    goto on_return;

-

-on_return:

-

-    pj_caching_pool_destroy( &caching_pool );

-

-    PJ_LOG(3,("test", ""));

- 

-    pj_thread_get_stack_info(pj_thread_this(), &filename, &line);

-    PJ_LOG(3,("test", "Stack max usage: %u, deepest: %s:%u", 

-	              pj_thread_get_stack_max_usage(pj_thread_this()),

-		      filename, line));

-    if (rc == 0)

-	PJ_LOG(3,("test", "Looks like everything is okay!.."));

-    else

-	PJ_LOG(3,("test", "Test completed with error(s)"));

-    return 0;

-}

-

-int test_main(void)

-{

-    PJ_USE_EXCEPTION;

-

-    PJ_TRY {

-        return test_inner();

-    }

-    PJ_DEFAULT {

-        int id = PJ_GET_EXCEPTION();

-        PJ_LOG(3,("test", "FATAL: unhandled exception id %d (%s)", 

-                  id, pj_exception_id_name(id)));

-    }

-    PJ_END;

-

-    return -1;

-}

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib.h>
+#ifdef _MSC_VER
+#  pragma warning(disable:4127)
+#endif
+
+#define DO_TEST(test)	do { \
+			    PJ_LOG(3, ("test", "Running %s...", #test));  \
+			    rc = test; \
+			    PJ_LOG(3, ("test",  \
+				       "%s(%d)",  \
+				       (rc ? "..ERROR" : "..success"), rc)); \
+			    if (rc!=0) goto on_return; \
+			} while (0)
+
+
+pj_pool_factory *mem;
+
+int param_echo_sock_type;
+const char *param_echo_server = ECHO_SERVER_ADDRESS;
+int param_echo_port = ECHO_SERVER_START_PORT;
+
+int test_inner(void)
+{
+    pj_caching_pool caching_pool;
+    const char *filename;
+    int line;
+    int rc = 0;
+
+    mem = &caching_pool.factory;
+
+    pj_log_set_level(3);
+    pj_log_set_decor(PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | 
+                     PJ_LOG_HAS_MICRO_SEC);
+
+    rc = pj_init();
+    if (rc != 0) {
+	app_perror("pj_init() error!!", rc);
+	return rc;
+    }
+    
+    pj_dump_config();
+    pj_caching_pool_init( &caching_pool, &pj_pool_factory_default_policy, 0 );
+
+#if INCLUDE_ERRNO_TEST
+    DO_TEST( errno_test() );
+#endif
+
+#if INCLUDE_TIMESTAMP_TEST
+    DO_TEST( timestamp_test() );
+#endif
+
+#if INCLUDE_EXCEPTION_TEST
+    DO_TEST( exception_test() );
+#endif
+
+#if INCLUDE_RAND_TEST
+    DO_TEST( rand_test() );
+#endif
+
+#if INCLUDE_LIST_TEST
+    DO_TEST( list_test() );
+#endif
+
+#if INCLUDE_POOL_TEST
+    DO_TEST( pool_test() );
+#endif
+
+#if INCLUDE_POOL_PERF_TEST
+    DO_TEST( pool_perf_test() );
+#endif
+
+#if INCLUDE_STRING_TEST
+    DO_TEST( string_test() );
+#endif
+    
+#if INCLUDE_FIFOBUF_TEST
+    DO_TEST( fifobuf_test() );
+#endif
+
+#if INCLUDE_RBTREE_TEST
+    DO_TEST( rbtree_test() );
+#endif
+
+#if INCLUDE_ATOMIC_TEST
+    DO_TEST( atomic_test() );
+#endif
+
+#if INCLUDE_MUTEX_TEST
+    DO_TEST( mutex_test() );
+#endif
+
+#if INCLUDE_TIMER_TEST
+    DO_TEST( timer_test() );
+#endif
+
+#if INCLUDE_SLEEP_TEST
+    DO_TEST( sleep_test() );
+#endif
+
+#if INCLUDE_THREAD_TEST
+    DO_TEST( thread_test() );
+#endif
+
+#if INCLUDE_SOCK_TEST
+    DO_TEST( sock_test() );
+#endif
+
+#if INCLUDE_SOCK_PERF_TEST
+    DO_TEST( sock_perf_test() );
+#endif
+
+#if INCLUDE_SELECT_TEST
+    DO_TEST( select_test() );
+#endif
+
+#if INCLUDE_UDP_IOQUEUE_TEST
+    DO_TEST( udp_ioqueue_test() );
+#endif
+
+#if PJ_HAS_TCP && INCLUDE_TCP_IOQUEUE_TEST
+    DO_TEST( tcp_ioqueue_test() );
+#endif
+
+#if INCLUDE_IOQUEUE_PERF_TEST
+    DO_TEST( ioqueue_perf_test() );
+#endif
+
+#if INCLUDE_FILE_TEST
+    DO_TEST( file_test() );
+#endif
+
+#if INCLUDE_ECHO_SERVER
+    //echo_server();
+    //echo_srv_sync();
+    udp_echo_srv_ioqueue();
+
+#elif INCLUDE_ECHO_CLIENT
+    if (param_echo_sock_type == 0)
+        param_echo_sock_type = PJ_SOCK_DGRAM;
+
+    echo_client( param_echo_sock_type, 
+                 param_echo_server, 
+                 param_echo_port);
+#endif
+
+    goto on_return;
+
+on_return:
+
+    pj_caching_pool_destroy( &caching_pool );
+
+    PJ_LOG(3,("test", ""));
+ 
+    pj_thread_get_stack_info(pj_thread_this(), &filename, &line);
+    PJ_LOG(3,("test", "Stack max usage: %u, deepest: %s:%u", 
+	              pj_thread_get_stack_max_usage(pj_thread_this()),
+		      filename, line));
+    if (rc == 0)
+	PJ_LOG(3,("test", "Looks like everything is okay!.."));
+    else
+	PJ_LOG(3,("test", "Test completed with error(s)"));
+    return 0;
+}
+
+int test_main(void)
+{
+    PJ_USE_EXCEPTION;
+
+    PJ_TRY {
+        return test_inner();
+    }
+    PJ_DEFAULT {
+        int id = PJ_GET_EXCEPTION();
+        PJ_LOG(3,("test", "FATAL: unhandled exception id %d (%s)", 
+                  id, pj_exception_id_name(id)));
+    }
+    PJ_END;
+
+    return -1;
+}
diff --git a/pjlib/src/pjlib-test/test.h b/pjlib/src/pjlib-test/test.h
index 4f3267b..8571d9d 100644
--- a/pjlib/src/pjlib-test/test.h
+++ b/pjlib/src/pjlib-test/test.h
@@ -1,111 +1,111 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#ifndef __PJLIB_TEST_H__

-#define __PJLIB_TEST_H__

-

-#include <pj/types.h>

-

-#define GROUP_LIBC                  1

-#define GROUP_OS                    1

-#define GROUP_DATA_STRUCTURE        1

-#define GROUP_NETWORK               1

-#define GROUP_FILE                  1

-

-#define INCLUDE_ERRNO_TEST          GROUP_LIBC

-#define INCLUDE_TIMESTAMP_TEST      GROUP_OS

-#define INCLUDE_EXCEPTION_TEST	    GROUP_LIBC

-#define INCLUDE_RAND_TEST	    GROUP_LIBC

-#define INCLUDE_LIST_TEST	    GROUP_DATA_STRUCTURE

-#define INCLUDE_POOL_TEST	    GROUP_LIBC

-#define INCLUDE_POOL_PERF_TEST	    (PJ_HAS_MALLOC && GROUP_LIBC)

-#define INCLUDE_STRING_TEST	    GROUP_DATA_STRUCTURE

-#define INCLUDE_FIFOBUF_TEST	    0	// GROUP_DATA_STRUCTURE

-#define INCLUDE_RBTREE_TEST	    GROUP_DATA_STRUCTURE

-#define INCLUDE_TIMER_TEST	    GROUP_DATA_STRUCTURE

-#define INCLUDE_ATOMIC_TEST         GROUP_OS

-#define INCLUDE_MUTEX_TEST	    GROUP_OS

-#define INCLUDE_SLEEP_TEST          GROUP_OS

-#define INCLUDE_THREAD_TEST         GROUP_OS 

-#define INCLUDE_SOCK_TEST	    GROUP_NETWORK

-#define INCLUDE_SOCK_PERF_TEST      GROUP_NETWORK

-#define INCLUDE_SELECT_TEST	    GROUP_NETWORK

-#define INCLUDE_UDP_IOQUEUE_TEST    GROUP_NETWORK

-#define INCLUDE_TCP_IOQUEUE_TEST    GROUP_NETWORK

-#define INCLUDE_IOQUEUE_PERF_TEST   GROUP_NETWORK

-#define INCLUDE_FILE_TEST           GROUP_FILE

-

-#define INCLUDE_ECHO_SERVER         0

-#define INCLUDE_ECHO_CLIENT         0

-

-

-#define ECHO_SERVER_MAX_THREADS     2

-#define ECHO_SERVER_START_PORT      65000

-#define ECHO_SERVER_ADDRESS         "compaq.home"

-#define ECHO_SERVER_DURATION_MSEC   (60*60*1000)

-

-#define ECHO_CLIENT_MAX_THREADS     6

-

-PJ_BEGIN_DECL

-

-extern int errno_test(void);

-extern int timestamp_test(void);

-extern int exception_test(void);

-extern int rand_test(void);

-extern int list_test(void);

-extern int pool_test(void);

-extern int pool_perf_test(void);

-extern int string_test(void);

-extern int fifobuf_test(void);

-extern int timer_test(void);

-extern int rbtree_test(void);

-extern int atomic_test(void);

-extern int mutex_test(void);

-extern int sleep_test(void);

-extern int thread_test(void);

-extern int sock_test(void);

-extern int sock_perf_test(void);

-extern int select_test(void);

-extern int udp_ioqueue_test(void);

-extern int tcp_ioqueue_test(void);

-extern int ioqueue_perf_test(void);

-extern int file_test(void);

-

-extern int echo_server(void);

-extern int echo_client(int sock_type, const char *server, int port);

-

-extern int echo_srv_sync(void);

-extern int udp_echo_srv_ioqueue(void);

-extern int echo_srv_common_loop(pj_atomic_t *bytes_counter);

-

-extern pj_pool_factory *mem;

-

-extern int          test_main(void);

-extern void         app_perror(const char *msg, pj_status_t err);

-extern pj_status_t  app_socket(int family, int type, int proto, int port,

-                               pj_sock_t *ptr_sock);

-extern pj_status_t  app_socketpair(int family, int type, int protocol,

-                                   pj_sock_t *server, pj_sock_t *client);

-

-//#define TRACE_(expr) PJ_LOG(3,expr)

-#define TRACE_(expr)

-

-PJ_END_DECL

-

-#endif	/* __PJLIB_TEST_H__ */

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJLIB_TEST_H__
+#define __PJLIB_TEST_H__
+
+#include <pj/types.h>
+
+#define GROUP_LIBC                  1
+#define GROUP_OS                    1
+#define GROUP_DATA_STRUCTURE        1
+#define GROUP_NETWORK               1
+#define GROUP_FILE                  1
+
+#define INCLUDE_ERRNO_TEST          GROUP_LIBC
+#define INCLUDE_TIMESTAMP_TEST      GROUP_OS
+#define INCLUDE_EXCEPTION_TEST	    GROUP_LIBC
+#define INCLUDE_RAND_TEST	    GROUP_LIBC
+#define INCLUDE_LIST_TEST	    GROUP_DATA_STRUCTURE
+#define INCLUDE_POOL_TEST	    GROUP_LIBC
+#define INCLUDE_POOL_PERF_TEST	    (PJ_HAS_MALLOC && GROUP_LIBC)
+#define INCLUDE_STRING_TEST	    GROUP_DATA_STRUCTURE
+#define INCLUDE_FIFOBUF_TEST	    0	// GROUP_DATA_STRUCTURE
+#define INCLUDE_RBTREE_TEST	    GROUP_DATA_STRUCTURE
+#define INCLUDE_TIMER_TEST	    GROUP_DATA_STRUCTURE
+#define INCLUDE_ATOMIC_TEST         GROUP_OS
+#define INCLUDE_MUTEX_TEST	    GROUP_OS
+#define INCLUDE_SLEEP_TEST          GROUP_OS
+#define INCLUDE_THREAD_TEST         GROUP_OS 
+#define INCLUDE_SOCK_TEST	    GROUP_NETWORK
+#define INCLUDE_SOCK_PERF_TEST      GROUP_NETWORK
+#define INCLUDE_SELECT_TEST	    GROUP_NETWORK
+#define INCLUDE_UDP_IOQUEUE_TEST    GROUP_NETWORK
+#define INCLUDE_TCP_IOQUEUE_TEST    GROUP_NETWORK
+#define INCLUDE_IOQUEUE_PERF_TEST   GROUP_NETWORK
+#define INCLUDE_FILE_TEST           GROUP_FILE
+
+#define INCLUDE_ECHO_SERVER         0
+#define INCLUDE_ECHO_CLIENT         0
+
+
+#define ECHO_SERVER_MAX_THREADS     2
+#define ECHO_SERVER_START_PORT      65000
+#define ECHO_SERVER_ADDRESS         "compaq.home"
+#define ECHO_SERVER_DURATION_MSEC   (60*60*1000)
+
+#define ECHO_CLIENT_MAX_THREADS     6
+
+PJ_BEGIN_DECL
+
+extern int errno_test(void);
+extern int timestamp_test(void);
+extern int exception_test(void);
+extern int rand_test(void);
+extern int list_test(void);
+extern int pool_test(void);
+extern int pool_perf_test(void);
+extern int string_test(void);
+extern int fifobuf_test(void);
+extern int timer_test(void);
+extern int rbtree_test(void);
+extern int atomic_test(void);
+extern int mutex_test(void);
+extern int sleep_test(void);
+extern int thread_test(void);
+extern int sock_test(void);
+extern int sock_perf_test(void);
+extern int select_test(void);
+extern int udp_ioqueue_test(void);
+extern int tcp_ioqueue_test(void);
+extern int ioqueue_perf_test(void);
+extern int file_test(void);
+
+extern int echo_server(void);
+extern int echo_client(int sock_type, const char *server, int port);
+
+extern int echo_srv_sync(void);
+extern int udp_echo_srv_ioqueue(void);
+extern int echo_srv_common_loop(pj_atomic_t *bytes_counter);
+
+extern pj_pool_factory *mem;
+
+extern int          test_main(void);
+extern void         app_perror(const char *msg, pj_status_t err);
+extern pj_status_t  app_socket(int family, int type, int proto, int port,
+                               pj_sock_t *ptr_sock);
+extern pj_status_t  app_socketpair(int family, int type, int protocol,
+                                   pj_sock_t *server, pj_sock_t *client);
+
+//#define TRACE_(expr) PJ_LOG(3,expr)
+#define TRACE_(expr)
+
+PJ_END_DECL
+
+#endif	/* __PJLIB_TEST_H__ */
+
diff --git a/pjlib/src/pjlib-test/thread.c b/pjlib/src/pjlib-test/thread.c
index 68264ea..2c7c41f 100644
--- a/pjlib/src/pjlib-test/thread.c
+++ b/pjlib/src/pjlib-test/thread.c
@@ -1,289 +1,289 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-/**

- * \page page_pjlib_thread_test Test: Thread Test

- *

- * This file contains \a thread_test() definition.

- *

- * \section thread_test_scope_sec Scope of Test

- * This tests:

- *  - whether PJ_THREAD_SUSPENDED flag works.

- *  - whether multithreading works.

- *  - whether thread timeslicing works, and threads have equal

- *    time-slice proportion.

- * 

- * APIs tested:

- *  - pj_thread_create()

- *  - pj_thread_register()

- *  - pj_thread_this()

- *  - pj_thread_get_name()

- *  - pj_thread_destroy()

- *  - pj_thread_resume()

- *  - pj_thread_sleep()

- *  - pj_thread_join()

- *  - pj_thread_destroy()

- *

- *

- * This file is <b>pjlib-test/thread.c</b>

- *

- * \include pjlib-test/thread.c

- */

-#if INCLUDE_THREAD_TEST

-

-#include <pjlib.h>

-

-#define THIS_FILE   "thread_test"

-

-static int quit_flag=0;

-

-/*

- * The thread's entry point.

- *

- * Each of the thread mainly will just execute the loop which

- * increments a variable.

- */

-static void* thread_proc(pj_uint32_t *pcounter)

-{

-    /* Test that pj_thread_register() works. */

-    pj_thread_desc desc;

-    pj_thread_t *this_thread;

-    pj_status_t rc;

-

-    rc = pj_thread_register("thread", desc, &this_thread);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error in pj_thread_register", rc);

-        return NULL;

-    }

-

-    /* Test that pj_thread_this() works */

-    this_thread = pj_thread_this();

-    if (this_thread == NULL) {

-        PJ_LOG(3,(THIS_FILE, "...error: pj_thread_this() returns NULL!"));

-        return NULL;

-    }

-

-    /* Test that pj_thread_get_name() works */

-    if (pj_thread_get_name(this_thread) == NULL) {

-        PJ_LOG(3,(THIS_FILE, "...error: pj_thread_get_name() returns NULL!"));

-        return NULL;

-    }

-

-    /* Main loop */

-    for (;!quit_flag;) {

-	(*pcounter)++;

-        //Must sleep if platform doesn't do time-slicing.

-	pj_thread_sleep(0);

-    }

-

-    return NULL;

-}

-

-/*

- * simple_thread()

- */

-static int simple_thread(const char *title, unsigned flags)

-{

-    pj_pool_t *pool;

-    pj_thread_t *thread;

-    pj_status_t rc;

-    pj_uint32_t counter = 0;

- 

-    PJ_LOG(3,(THIS_FILE, "..%s", title));

-    

-    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);

-    if (!pool)

-	return -1000;

-

-    quit_flag = 0;

-

-    rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc,

-			  &counter,

-			  PJ_THREAD_DEFAULT_STACK_SIZE,

-			  flags,

-			  &thread);

-

-    if (rc != PJ_SUCCESS) {

-	app_perror("...error: unable to create thread", rc);

-	return -1010;

-    }

-

-    if (flags & PJ_THREAD_SUSPENDED) {

-	rc = pj_thread_resume(thread);

-	if (rc != PJ_SUCCESS) {

-	    app_perror("...error: resume thread error", rc);

-	    return -1020;

-	}

-    }

-    

-    PJ_LOG(3,(THIS_FILE, "..waiting for thread to quit.."));

-

-    quit_flag = 1;

-    pj_thread_join(thread);

-

-    pj_pool_release(pool);

-

-    PJ_LOG(3,(THIS_FILE, "...%s success", title));

-    return PJ_SUCCESS;

-}

-

-

-/*

- * timeslice_test()

- */

-static int timeslice_test(void)

-{

-    enum { NUM_THREADS = 4 };

-    pj_pool_t *pool;

-    pj_uint32_t counter[NUM_THREADS], lowest, highest, diff;

-    pj_thread_t *thread[NUM_THREADS];

-    int i;

-    pj_status_t rc;

-

-    quit_flag = 0;

-

-    pool = pj_pool_create(mem, NULL, 4096, 0, NULL);

-    if (!pool)

-        return -10;

-

-    PJ_LOG(3,(THIS_FILE, "..timeslice testing with %d threads", NUM_THREADS));

-

-    /* Create all threads in suspended mode. */

-    for (i=0; i<NUM_THREADS; ++i) {

-        counter[i] = 0;

-        rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc, 

-			      &counter[i], 

-                              PJ_THREAD_DEFAULT_STACK_SIZE, 

-                              PJ_THREAD_SUSPENDED, 

-                              &thread[i]);

-        if (rc!=PJ_SUCCESS) {

-            app_perror("...ERROR in pj_thread_create()", rc);

-            return -20;

-        }

-    }

-

-    /* Sleep for 1 second.

-     * The purpose of this is to test whether all threads are suspended.

-     */

-    pj_thread_sleep(1000);

-

-    /* Check that all counters are still zero. */

-    for (i=0; i<NUM_THREADS; ++i) {

-        if (counter[i] != 0) {

-            PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!", 

-		      i));

-            return -30;

-        }

-    }

-

-    /* Now resume all threads. */

-    for (i=0; i<NUM_THREADS; ++i) {

-        rc = pj_thread_resume(thread[i]);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...ERROR in pj_thread_resume()", rc);

-            return -40;

-        }

-    }

-

-    /* Main thread sleeps for some time to allow threads to run. 

-     * The longer we sleep, the more accurate the calculation will be,

-     * but it'll make user waits for longer for the test to finish.

-     */

-    pj_thread_sleep(5000);

-

-    /* Signal all threads to quit. */

-    quit_flag = 1;

-

-    /* Wait until all threads quit, then destroy. */

-    for (i=0; i<NUM_THREADS; ++i) {

-        rc = pj_thread_join(thread[i]);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...ERROR in pj_thread_join()", rc);

-            return -50;

-        }

-        rc = pj_thread_destroy(thread[i]);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...ERROR in pj_thread_destroy()", rc);

-            return -60;

-        }

-    }

-

-    /* Now examine the value of the counters.

-     * Check that all threads had equal proportion of processing.

-     */

-    lowest = 0xFFFFFFFF;

-    highest = 0;

-    for (i=0; i<NUM_THREADS; ++i) {

-        if (counter[i] < lowest)

-            lowest = counter[i];

-        if (counter[i] > highest)

-            highest = counter[i];

-    }

-

-    /* Check that all threads are running. */

-    if (lowest < 2) {

-        PJ_LOG(3,(THIS_FILE, "...ERROR: not all threads were running!"));

-        return -70;

-    }

-

-    /* The difference between lowest and higest should be lower than 50%.

-     */

-    diff = (highest-lowest)*100 / ((highest+lowest)/2);

-    if ( diff >= 50) {

-        PJ_LOG(3,(THIS_FILE, "...ERROR: thread didn't have equal timeslice!"));

-        PJ_LOG(3,(THIS_FILE, ".....lowest counter=%u, highest counter=%u, diff=%u%%",

-                             lowest, highest, diff));

-        return -80;

-    } else {

-        PJ_LOG(3,(THIS_FILE, 

-                  "...info: timeslice diff between lowest & highest=%u%%",

-                  diff));

-    }

-

-    return 0;

-}

-

-int thread_test(void)

-{

-    int rc;

-

-    rc = simple_thread("simple thread test", 0);

-    if (rc != PJ_SUCCESS)

-	return rc;

-    

-    rc = simple_thread("suspended thread test", PJ_THREAD_SUSPENDED);

-    if (rc != PJ_SUCCESS)

-	return rc;

-    

-    rc = timeslice_test();

-    if (rc != PJ_SUCCESS)

-	return rc;

-

-    return rc;

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_thread_test;

-#endif	/* INCLUDE_THREAD_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+/**
+ * \page page_pjlib_thread_test Test: Thread Test
+ *
+ * This file contains \a thread_test() definition.
+ *
+ * \section thread_test_scope_sec Scope of Test
+ * This tests:
+ *  - whether PJ_THREAD_SUSPENDED flag works.
+ *  - whether multithreading works.
+ *  - whether thread timeslicing works, and threads have equal
+ *    time-slice proportion.
+ * 
+ * APIs tested:
+ *  - pj_thread_create()
+ *  - pj_thread_register()
+ *  - pj_thread_this()
+ *  - pj_thread_get_name()
+ *  - pj_thread_destroy()
+ *  - pj_thread_resume()
+ *  - pj_thread_sleep()
+ *  - pj_thread_join()
+ *  - pj_thread_destroy()
+ *
+ *
+ * This file is <b>pjlib-test/thread.c</b>
+ *
+ * \include pjlib-test/thread.c
+ */
+#if INCLUDE_THREAD_TEST
+
+#include <pjlib.h>
+
+#define THIS_FILE   "thread_test"
+
+static int quit_flag=0;
+
+/*
+ * The thread's entry point.
+ *
+ * Each of the thread mainly will just execute the loop which
+ * increments a variable.
+ */
+static void* thread_proc(pj_uint32_t *pcounter)
+{
+    /* Test that pj_thread_register() works. */
+    pj_thread_desc desc;
+    pj_thread_t *this_thread;
+    pj_status_t rc;
+
+    rc = pj_thread_register("thread", desc, &this_thread);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error in pj_thread_register", rc);
+        return NULL;
+    }
+
+    /* Test that pj_thread_this() works */
+    this_thread = pj_thread_this();
+    if (this_thread == NULL) {
+        PJ_LOG(3,(THIS_FILE, "...error: pj_thread_this() returns NULL!"));
+        return NULL;
+    }
+
+    /* Test that pj_thread_get_name() works */
+    if (pj_thread_get_name(this_thread) == NULL) {
+        PJ_LOG(3,(THIS_FILE, "...error: pj_thread_get_name() returns NULL!"));
+        return NULL;
+    }
+
+    /* Main loop */
+    for (;!quit_flag;) {
+	(*pcounter)++;
+        //Must sleep if platform doesn't do time-slicing.
+	pj_thread_sleep(0);
+    }
+
+    return NULL;
+}
+
+/*
+ * simple_thread()
+ */
+static int simple_thread(const char *title, unsigned flags)
+{
+    pj_pool_t *pool;
+    pj_thread_t *thread;
+    pj_status_t rc;
+    pj_uint32_t counter = 0;
+ 
+    PJ_LOG(3,(THIS_FILE, "..%s", title));
+    
+    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
+    if (!pool)
+	return -1000;
+
+    quit_flag = 0;
+
+    rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc,
+			  &counter,
+			  PJ_THREAD_DEFAULT_STACK_SIZE,
+			  flags,
+			  &thread);
+
+    if (rc != PJ_SUCCESS) {
+	app_perror("...error: unable to create thread", rc);
+	return -1010;
+    }
+
+    if (flags & PJ_THREAD_SUSPENDED) {
+	rc = pj_thread_resume(thread);
+	if (rc != PJ_SUCCESS) {
+	    app_perror("...error: resume thread error", rc);
+	    return -1020;
+	}
+    }
+    
+    PJ_LOG(3,(THIS_FILE, "..waiting for thread to quit.."));
+
+    quit_flag = 1;
+    pj_thread_join(thread);
+
+    pj_pool_release(pool);
+
+    PJ_LOG(3,(THIS_FILE, "...%s success", title));
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * timeslice_test()
+ */
+static int timeslice_test(void)
+{
+    enum { NUM_THREADS = 4 };
+    pj_pool_t *pool;
+    pj_uint32_t counter[NUM_THREADS], lowest, highest, diff;
+    pj_thread_t *thread[NUM_THREADS];
+    int i;
+    pj_status_t rc;
+
+    quit_flag = 0;
+
+    pool = pj_pool_create(mem, NULL, 4096, 0, NULL);
+    if (!pool)
+        return -10;
+
+    PJ_LOG(3,(THIS_FILE, "..timeslice testing with %d threads", NUM_THREADS));
+
+    /* Create all threads in suspended mode. */
+    for (i=0; i<NUM_THREADS; ++i) {
+        counter[i] = 0;
+        rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc, 
+			      &counter[i], 
+                              PJ_THREAD_DEFAULT_STACK_SIZE, 
+                              PJ_THREAD_SUSPENDED, 
+                              &thread[i]);
+        if (rc!=PJ_SUCCESS) {
+            app_perror("...ERROR in pj_thread_create()", rc);
+            return -20;
+        }
+    }
+
+    /* Sleep for 1 second.
+     * The purpose of this is to test whether all threads are suspended.
+     */
+    pj_thread_sleep(1000);
+
+    /* Check that all counters are still zero. */
+    for (i=0; i<NUM_THREADS; ++i) {
+        if (counter[i] != 0) {
+            PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!", 
+		      i));
+            return -30;
+        }
+    }
+
+    /* Now resume all threads. */
+    for (i=0; i<NUM_THREADS; ++i) {
+        rc = pj_thread_resume(thread[i]);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...ERROR in pj_thread_resume()", rc);
+            return -40;
+        }
+    }
+
+    /* Main thread sleeps for some time to allow threads to run. 
+     * The longer we sleep, the more accurate the calculation will be,
+     * but it'll make user waits for longer for the test to finish.
+     */
+    pj_thread_sleep(5000);
+
+    /* Signal all threads to quit. */
+    quit_flag = 1;
+
+    /* Wait until all threads quit, then destroy. */
+    for (i=0; i<NUM_THREADS; ++i) {
+        rc = pj_thread_join(thread[i]);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...ERROR in pj_thread_join()", rc);
+            return -50;
+        }
+        rc = pj_thread_destroy(thread[i]);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...ERROR in pj_thread_destroy()", rc);
+            return -60;
+        }
+    }
+
+    /* Now examine the value of the counters.
+     * Check that all threads had equal proportion of processing.
+     */
+    lowest = 0xFFFFFFFF;
+    highest = 0;
+    for (i=0; i<NUM_THREADS; ++i) {
+        if (counter[i] < lowest)
+            lowest = counter[i];
+        if (counter[i] > highest)
+            highest = counter[i];
+    }
+
+    /* Check that all threads are running. */
+    if (lowest < 2) {
+        PJ_LOG(3,(THIS_FILE, "...ERROR: not all threads were running!"));
+        return -70;
+    }
+
+    /* The difference between lowest and higest should be lower than 50%.
+     */
+    diff = (highest-lowest)*100 / ((highest+lowest)/2);
+    if ( diff >= 50) {
+        PJ_LOG(3,(THIS_FILE, "...ERROR: thread didn't have equal timeslice!"));
+        PJ_LOG(3,(THIS_FILE, ".....lowest counter=%u, highest counter=%u, diff=%u%%",
+                             lowest, highest, diff));
+        return -80;
+    } else {
+        PJ_LOG(3,(THIS_FILE, 
+                  "...info: timeslice diff between lowest & highest=%u%%",
+                  diff));
+    }
+
+    return 0;
+}
+
+int thread_test(void)
+{
+    int rc;
+
+    rc = simple_thread("simple thread test", 0);
+    if (rc != PJ_SUCCESS)
+	return rc;
+    
+    rc = simple_thread("suspended thread test", PJ_THREAD_SUSPENDED);
+    if (rc != PJ_SUCCESS)
+	return rc;
+    
+    rc = timeslice_test();
+    if (rc != PJ_SUCCESS)
+	return rc;
+
+    return rc;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_thread_test;
+#endif	/* INCLUDE_THREAD_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/timer.c b/pjlib/src/pjlib-test/timer.c
index 2ae5520..8b2ebe5 100644
--- a/pjlib/src/pjlib-test/timer.c
+++ b/pjlib/src/pjlib-test/timer.c
@@ -1,186 +1,186 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-

-/**

- * \page page_pjlib_timer_test Test: Timer

- *

- * This file provides implementation of \b timer_test(). It tests the

- * functionality of the timer heap.

- *

- *

- * This file is <b>pjlib-test/timer.c</b>

- *

- * \include pjlib-test/timer.c

- */

-

-

-#if INCLUDE_TIMER_TEST

-

-#include <pjlib.h>

-

-#define LOOP		16

-#define MIN_COUNT	250

-#define MAX_COUNT	(LOOP * MIN_COUNT)

-#define MIN_DELAY	2

-#define	D		(MAX_COUNT / 32000)

-#define DELAY		(D < MIN_DELAY ? MIN_DELAY : D)

-#define THIS_FILE	"timer_test"

-

-

-static void timer_callback(pj_timer_heap_t *ht, pj_timer_entry *e)

-{

-    PJ_UNUSED_ARG(ht);

-    PJ_UNUSED_ARG(e);

-}

-

-static int test_timer_heap(void)

-{

-    int i, j;

-    pj_timer_entry *entry;

-    pj_pool_t *pool;

-    pj_timer_heap_t *timer;

-    pj_time_val delay;

-    pj_status_t rc;    int err=0;

-    unsigned size, count;

-

-    size = pj_timer_heap_mem_size(MAX_COUNT)+MAX_COUNT*sizeof(pj_timer_entry);

-    pool = pj_pool_create( mem, NULL, size, 4000, NULL);

-    if (!pool) {

-	PJ_LOG(3,("test", "...error: unable to create pool of %u bytes",

-		  size));

-	return -10;

-    }

-

-    entry = (pj_timer_entry*)pj_pool_calloc(pool, MAX_COUNT, sizeof(*entry));

-    if (!entry)

-	return -20;

-

-    for (i=0; i<MAX_COUNT; ++i) {

-	entry[i].cb = &timer_callback;

-    }

-    rc = pj_timer_heap_create(pool, MAX_COUNT, &timer);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error: unable to create timer heap", rc);

-	return -30;

-    }

-

-    count = MIN_COUNT;

-    for (i=0; i<LOOP; ++i) {

-	int early = 0;

-	int done=0;

-	int cancelled=0;

-	int rc;

-	pj_timestamp t1, t2, t_sched, t_cancel, t_poll;

-	pj_time_val now, expire;

-

-	pj_gettimeofday(&now);

-	pj_srand(now.sec);

-	t_sched.u32.lo = t_cancel.u32.lo = t_poll.u32.lo = 0;

-

-	// Register timers

-	for (j=0; j<(int)count; ++j) {

-	    delay.sec = pj_rand() % DELAY;

-	    delay.msec = pj_rand() % 1000;

-

-	    // Schedule timer

-	    pj_get_timestamp(&t1);

-	    rc = pj_timer_heap_schedule(timer, &entry[j], &delay);

-	    if (rc != 0)

-		return -40;

-	    pj_get_timestamp(&t2);

-

-	    t_sched.u32.lo += (t2.u32.lo - t1.u32.lo);

-

-	    // Poll timers.

-	    pj_get_timestamp(&t1);

-	    rc = pj_timer_heap_poll(timer, NULL);

-	    pj_get_timestamp(&t2);

-	    if (rc > 0) {

-		t_poll.u32.lo += (t2.u32.lo - t1.u32.lo);

-		early += rc;

-	    }

-	}

-

-	// Set the time where all timers should finish

-	pj_gettimeofday(&expire);

-	delay.sec = DELAY; 

-	delay.msec = 0;

-	PJ_TIME_VAL_ADD(expire, delay);

-

-	// Wait unfil all timers finish, cancel some of them.

-	do {

-	    int index = pj_rand() % count;

-	    pj_get_timestamp(&t1);

-	    rc = pj_timer_heap_cancel(timer, &entry[index]);

-	    pj_get_timestamp(&t2);

-	    if (rc > 0) {

-		cancelled += rc;

-		t_cancel.u32.lo += (t2.u32.lo - t1.u32.lo);

-	    }

-

-	    pj_gettimeofday(&now);

-

-	    pj_get_timestamp(&t1);

-	    rc = pj_timer_heap_poll(timer, NULL);

-	    pj_get_timestamp(&t2);

-	    if (rc > 0) {

-		done += rc;

-		t_poll.u32.lo += (t2.u32.lo - t1.u32.lo);

-	    }

-

-	} while (PJ_TIME_VAL_LTE(now, expire)&&pj_timer_heap_count(timer) > 0);

-

-	if (pj_timer_heap_count(timer)) {

-	    PJ_LOG(3, (THIS_FILE, "ERROR: %d timers left", 

-		       pj_timer_heap_count(timer)));

-	    ++err;

-	}

-	t_sched.u32.lo /= count; 

-	t_cancel.u32.lo /= count;

-	t_poll.u32.lo /= count;

-	PJ_LOG(4, (THIS_FILE, 

-	        "...ok (count:%d, early:%d, cancelled:%d, "

-		"sched:%d, cancel:%d poll:%d)", 

-		count, early, cancelled, t_sched.u32.lo, t_cancel.u32.lo,

-		t_poll.u32.lo));

-

-	count = count * 2;

-	if (count > MAX_COUNT)

-	    break;

-    }

-

-    pj_pool_release(pool);

-    return err;

-}

-

-

-int timer_test()

-{

-    return test_timer_heap();

-}

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_timer_test;

-#endif	/* INCLUDE_TIMER_TEST */

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+
+/**
+ * \page page_pjlib_timer_test Test: Timer
+ *
+ * This file provides implementation of \b timer_test(). It tests the
+ * functionality of the timer heap.
+ *
+ *
+ * This file is <b>pjlib-test/timer.c</b>
+ *
+ * \include pjlib-test/timer.c
+ */
+
+
+#if INCLUDE_TIMER_TEST
+
+#include <pjlib.h>
+
+#define LOOP		16
+#define MIN_COUNT	250
+#define MAX_COUNT	(LOOP * MIN_COUNT)
+#define MIN_DELAY	2
+#define	D		(MAX_COUNT / 32000)
+#define DELAY		(D < MIN_DELAY ? MIN_DELAY : D)
+#define THIS_FILE	"timer_test"
+
+
+static void timer_callback(pj_timer_heap_t *ht, pj_timer_entry *e)
+{
+    PJ_UNUSED_ARG(ht);
+    PJ_UNUSED_ARG(e);
+}
+
+static int test_timer_heap(void)
+{
+    int i, j;
+    pj_timer_entry *entry;
+    pj_pool_t *pool;
+    pj_timer_heap_t *timer;
+    pj_time_val delay;
+    pj_status_t rc;    int err=0;
+    unsigned size, count;
+
+    size = pj_timer_heap_mem_size(MAX_COUNT)+MAX_COUNT*sizeof(pj_timer_entry);
+    pool = pj_pool_create( mem, NULL, size, 4000, NULL);
+    if (!pool) {
+	PJ_LOG(3,("test", "...error: unable to create pool of %u bytes",
+		  size));
+	return -10;
+    }
+
+    entry = (pj_timer_entry*)pj_pool_calloc(pool, MAX_COUNT, sizeof(*entry));
+    if (!entry)
+	return -20;
+
+    for (i=0; i<MAX_COUNT; ++i) {
+	entry[i].cb = &timer_callback;
+    }
+    rc = pj_timer_heap_create(pool, MAX_COUNT, &timer);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error: unable to create timer heap", rc);
+	return -30;
+    }
+
+    count = MIN_COUNT;
+    for (i=0; i<LOOP; ++i) {
+	int early = 0;
+	int done=0;
+	int cancelled=0;
+	int rc;
+	pj_timestamp t1, t2, t_sched, t_cancel, t_poll;
+	pj_time_val now, expire;
+
+	pj_gettimeofday(&now);
+	pj_srand(now.sec);
+	t_sched.u32.lo = t_cancel.u32.lo = t_poll.u32.lo = 0;
+
+	// Register timers
+	for (j=0; j<(int)count; ++j) {
+	    delay.sec = pj_rand() % DELAY;
+	    delay.msec = pj_rand() % 1000;
+
+	    // Schedule timer
+	    pj_get_timestamp(&t1);
+	    rc = pj_timer_heap_schedule(timer, &entry[j], &delay);
+	    if (rc != 0)
+		return -40;
+	    pj_get_timestamp(&t2);
+
+	    t_sched.u32.lo += (t2.u32.lo - t1.u32.lo);
+
+	    // Poll timers.
+	    pj_get_timestamp(&t1);
+	    rc = pj_timer_heap_poll(timer, NULL);
+	    pj_get_timestamp(&t2);
+	    if (rc > 0) {
+		t_poll.u32.lo += (t2.u32.lo - t1.u32.lo);
+		early += rc;
+	    }
+	}
+
+	// Set the time where all timers should finish
+	pj_gettimeofday(&expire);
+	delay.sec = DELAY; 
+	delay.msec = 0;
+	PJ_TIME_VAL_ADD(expire, delay);
+
+	// Wait unfil all timers finish, cancel some of them.
+	do {
+	    int index = pj_rand() % count;
+	    pj_get_timestamp(&t1);
+	    rc = pj_timer_heap_cancel(timer, &entry[index]);
+	    pj_get_timestamp(&t2);
+	    if (rc > 0) {
+		cancelled += rc;
+		t_cancel.u32.lo += (t2.u32.lo - t1.u32.lo);
+	    }
+
+	    pj_gettimeofday(&now);
+
+	    pj_get_timestamp(&t1);
+	    rc = pj_timer_heap_poll(timer, NULL);
+	    pj_get_timestamp(&t2);
+	    if (rc > 0) {
+		done += rc;
+		t_poll.u32.lo += (t2.u32.lo - t1.u32.lo);
+	    }
+
+	} while (PJ_TIME_VAL_LTE(now, expire)&&pj_timer_heap_count(timer) > 0);
+
+	if (pj_timer_heap_count(timer)) {
+	    PJ_LOG(3, (THIS_FILE, "ERROR: %d timers left", 
+		       pj_timer_heap_count(timer)));
+	    ++err;
+	}
+	t_sched.u32.lo /= count; 
+	t_cancel.u32.lo /= count;
+	t_poll.u32.lo /= count;
+	PJ_LOG(4, (THIS_FILE, 
+	        "...ok (count:%d, early:%d, cancelled:%d, "
+		"sched:%d, cancel:%d poll:%d)", 
+		count, early, cancelled, t_sched.u32.lo, t_cancel.u32.lo,
+		t_poll.u32.lo));
+
+	count = count * 2;
+	if (count > MAX_COUNT)
+	    break;
+    }
+
+    pj_pool_release(pool);
+    return err;
+}
+
+
+int timer_test()
+{
+    return test_timer_heap();
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_timer_test;
+#endif	/* INCLUDE_TIMER_TEST */
+
+
diff --git a/pjlib/src/pjlib-test/timestamp.c b/pjlib/src/pjlib-test/timestamp.c
index ec10351..67e47c1 100644
--- a/pjlib/src/pjlib-test/timestamp.c
+++ b/pjlib/src/pjlib-test/timestamp.c
@@ -1,143 +1,143 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pj/os.h>

-#include <pj/log.h>

-

-

-/**

- * \page page_pjlib_timestamp_test Test: Timestamp

- *

- * This file provides implementation of timestamp_test()

- *

- * \section timestamp_test_sec Scope of the Test

- *

- * This tests whether timestamp API works.

- *

- * API tested:

- *  - pj_get_timestamp_freq()

- *  - pj_get_timestamp()

- *  - pj_elapsed_usec()

- *  - PJ_LOG()

- *

- *

- * This file is <b>pjlib-test/timestamp.c</b>

- *

- * \include pjlib-test/timestamp.c

- */

-

-#if INCLUDE_TIMESTAMP_TEST

-

-#define THIS_FILE   "timestamp"

-

-int timestamp_test(void)

-{

-    enum { CONSECUTIVE_LOOP = 1000 };

-    volatile unsigned i;

-    pj_timestamp freq, t1, t2;

-    unsigned elapsed;

-    pj_status_t rc;

-

-    PJ_LOG(3,(THIS_FILE, "...Testing timestamp (high res time)"));

-    

-    /* Get and display timestamp frequency. */

-    if ((rc=pj_get_timestamp_freq(&freq)) != PJ_SUCCESS) {

-	app_perror("...ERROR: get timestamp freq", rc);

-	return -1000;

-    }

-

-    PJ_LOG(3,(THIS_FILE, "....frequency: hiword=%lu loword=%lu", 

-			freq.u32.hi, freq.u32.lo));

-

-    PJ_LOG(3,(THIS_FILE, "...checking if time can run backwards (pls wait).."));

-

-    /*

-     * Check if consecutive readings should yield timestamp value

-     * that is bigger than previous value.

-     * First we get the first timestamp.

-     */

-    rc = pj_get_timestamp(&t1);

-    if (rc != PJ_SUCCESS) {

-	app_perror("...ERROR: get timestamp", rc);

-	return -1001;

-    }

-    for (i=0; i<CONSECUTIVE_LOOP; ++i) {

-        /*

-	volatile unsigned j;

-	for (j=0; j<1000; ++j)

-	    ;

-         */

-        pj_thread_sleep(1);

-	rc = pj_get_timestamp(&t2);

-	if (rc != PJ_SUCCESS) {

-	    app_perror("...ERROR: get timestamp", rc);

-	    return -1002;

-	}

-	/* compare t2 with t1, expecting t2 >= t1. */

-	if (t2.u32.hi < t1.u32.hi ||

-	    (t2.u32.hi == t1.u32.hi && t2.u32.lo < t1.u32.lo))

-	{

-	    PJ_LOG(3,(THIS_FILE, "...ERROR: timestamp runs backwards!"));

-	    return -1003;

-	}

-    }

-

-    /* 

-     * Simple test to time some loop. 

-     */

-    PJ_LOG(3,(THIS_FILE, "....testing simple 1000000 loop"));

-

-

-    /* Mark start time. */

-    if ((rc=pj_get_timestamp(&t1)) != PJ_SUCCESS) {

-	app_perror("....error: cat't get timestamp", rc);

-	return -1010;

-    }

-

-    /* Loop.. */

-    for (i=0; i<1000000; ++i)

-	;

-

-    /* Mark end time. */

-    pj_get_timestamp(&t2);

-

-    /* Get elapsed time in usec. */

-    elapsed = pj_elapsed_usec(&t1, &t2);

-    PJ_LOG(3,(THIS_FILE, "....elapsed: %u usec", (unsigned)elapsed));

-

-    /* See if elapsed time is reasonable. */

-    if (elapsed < 1 || elapsed > 100000) {

-	PJ_LOG(3,(THIS_FILE, "....error: elapsed time outside window (%u, "

-			     "t1.u32.hi=%u, t1.u32.lo=%u, "

-			     "t2.u32.hi=%u, t2.u32.lo=%u)",

-			     elapsed, 

-			     t1.u32.hi, t1.u32.lo, t2.u32.hi, t2.u32.lo));

-	return -1030;

-    }

-    return 0;

-}

-

-

-#else

-/* To prevent warning about "translation unit is empty"

- * when this test is disabled. 

- */

-int dummy_timestamp_test;

-#endif	/* INCLUDE_TIMESTAMP_TEST */

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pj/os.h>
+#include <pj/log.h>
+
+
+/**
+ * \page page_pjlib_timestamp_test Test: Timestamp
+ *
+ * This file provides implementation of timestamp_test()
+ *
+ * \section timestamp_test_sec Scope of the Test
+ *
+ * This tests whether timestamp API works.
+ *
+ * API tested:
+ *  - pj_get_timestamp_freq()
+ *  - pj_get_timestamp()
+ *  - pj_elapsed_usec()
+ *  - PJ_LOG()
+ *
+ *
+ * This file is <b>pjlib-test/timestamp.c</b>
+ *
+ * \include pjlib-test/timestamp.c
+ */
+
+#if INCLUDE_TIMESTAMP_TEST
+
+#define THIS_FILE   "timestamp"
+
+int timestamp_test(void)
+{
+    enum { CONSECUTIVE_LOOP = 1000 };
+    volatile unsigned i;
+    pj_timestamp freq, t1, t2;
+    unsigned elapsed;
+    pj_status_t rc;
+
+    PJ_LOG(3,(THIS_FILE, "...Testing timestamp (high res time)"));
+    
+    /* Get and display timestamp frequency. */
+    if ((rc=pj_get_timestamp_freq(&freq)) != PJ_SUCCESS) {
+	app_perror("...ERROR: get timestamp freq", rc);
+	return -1000;
+    }
+
+    PJ_LOG(3,(THIS_FILE, "....frequency: hiword=%lu loword=%lu", 
+			freq.u32.hi, freq.u32.lo));
+
+    PJ_LOG(3,(THIS_FILE, "...checking if time can run backwards (pls wait).."));
+
+    /*
+     * Check if consecutive readings should yield timestamp value
+     * that is bigger than previous value.
+     * First we get the first timestamp.
+     */
+    rc = pj_get_timestamp(&t1);
+    if (rc != PJ_SUCCESS) {
+	app_perror("...ERROR: get timestamp", rc);
+	return -1001;
+    }
+    for (i=0; i<CONSECUTIVE_LOOP; ++i) {
+        /*
+	volatile unsigned j;
+	for (j=0; j<1000; ++j)
+	    ;
+         */
+        pj_thread_sleep(1);
+	rc = pj_get_timestamp(&t2);
+	if (rc != PJ_SUCCESS) {
+	    app_perror("...ERROR: get timestamp", rc);
+	    return -1002;
+	}
+	/* compare t2 with t1, expecting t2 >= t1. */
+	if (t2.u32.hi < t1.u32.hi ||
+	    (t2.u32.hi == t1.u32.hi && t2.u32.lo < t1.u32.lo))
+	{
+	    PJ_LOG(3,(THIS_FILE, "...ERROR: timestamp runs backwards!"));
+	    return -1003;
+	}
+    }
+
+    /* 
+     * Simple test to time some loop. 
+     */
+    PJ_LOG(3,(THIS_FILE, "....testing simple 1000000 loop"));
+
+
+    /* Mark start time. */
+    if ((rc=pj_get_timestamp(&t1)) != PJ_SUCCESS) {
+	app_perror("....error: cat't get timestamp", rc);
+	return -1010;
+    }
+
+    /* Loop.. */
+    for (i=0; i<1000000; ++i)
+	;
+
+    /* Mark end time. */
+    pj_get_timestamp(&t2);
+
+    /* Get elapsed time in usec. */
+    elapsed = pj_elapsed_usec(&t1, &t2);
+    PJ_LOG(3,(THIS_FILE, "....elapsed: %u usec", (unsigned)elapsed));
+
+    /* See if elapsed time is reasonable. */
+    if (elapsed < 1 || elapsed > 100000) {
+	PJ_LOG(3,(THIS_FILE, "....error: elapsed time outside window (%u, "
+			     "t1.u32.hi=%u, t1.u32.lo=%u, "
+			     "t2.u32.hi=%u, t2.u32.lo=%u)",
+			     elapsed, 
+			     t1.u32.hi, t1.u32.lo, t2.u32.hi, t2.u32.lo));
+	return -1030;
+    }
+    return 0;
+}
+
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_timestamp_test;
+#endif	/* INCLUDE_TIMESTAMP_TEST */
+
diff --git a/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c b/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c
index 2dec91c..8ede493 100644
--- a/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c
+++ b/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c
@@ -1,211 +1,211 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include <pjlib.h>

-#include "test.h"

-

-static pj_ioqueue_key_t *key;

-static pj_atomic_t *total_bytes;

-

-struct op_key

-{

-    pj_ioqueue_op_key_t  op_key_;

-    struct op_key       *peer;

-    char                *buffer;

-    pj_size_t            size;

-    int                  is_pending;

-    pj_status_t          last_err;

-    pj_sockaddr_in       addr;

-    int                  addrlen;

-};

-

-static void on_read_complete(pj_ioqueue_key_t *key, 

-                             pj_ioqueue_op_key_t *op_key, 

-                             pj_ssize_t bytes_received)

-{

-    pj_status_t rc;

-    struct op_key *recv_rec = (struct op_key *)op_key;

-

-    for (;;) {

-        struct op_key *send_rec = recv_rec->peer;

-        recv_rec->is_pending = 0;

-

-        if (bytes_received < 0) {

-            if (-bytes_received != recv_rec->last_err) {

-                recv_rec->last_err = -bytes_received;

-                app_perror("...error receiving data", -bytes_received);

-            }

-        } else if (bytes_received == 0) {

-            /* note: previous error, or write callback */

-        } else {

-            pj_atomic_add(total_bytes, bytes_received);

-

-            if (!send_rec->is_pending) {

-                pj_ssize_t sent = bytes_received;

-                pj_memcpy(send_rec->buffer, recv_rec->buffer, bytes_received);

-                pj_memcpy(&send_rec->addr, &recv_rec->addr, recv_rec->addrlen);

-                send_rec->addrlen = recv_rec->addrlen;

-                rc = pj_ioqueue_sendto(key, &send_rec->op_key_, 

-                                       send_rec->buffer, &sent, 0,

-                                       &send_rec->addr, send_rec->addrlen);

-                send_rec->is_pending = (rc==PJ_EPENDING);

-

-                if (rc!=PJ_SUCCESS && rc!=PJ_EPENDING) {

-                    app_perror("...send error(1)", rc);

-                }

-            }

-        }

-

-        if (!send_rec->is_pending) {

-            bytes_received = recv_rec->size;

-            rc = pj_ioqueue_recvfrom(key, &recv_rec->op_key_, 

-                                     recv_rec->buffer, &bytes_received, 0,

-                                     &recv_rec->addr, &recv_rec->addrlen);

-            recv_rec->is_pending = (rc==PJ_EPENDING);

-            if (rc == PJ_SUCCESS) {

-                /* fall through next loop. */

-            } else if (rc == PJ_EPENDING) {

-                /* quit callback. */

-                break;

-            } else {

-                /* error */

-                app_perror("...recv error", rc);

-                recv_rec->last_err = rc;

-

-                bytes_received = 0;

-                /* fall through next loop. */

-            }

-        } else {

-            /* recv will be done when write completion callback is called. */

-            break;

-        }

-    }

-}

-

-static void on_write_complete(pj_ioqueue_key_t *key, 

-                              pj_ioqueue_op_key_t *op_key, 

-                              pj_ssize_t bytes_sent)

-{

-    struct op_key *send_rec = (struct op_key*)op_key;

-

-    if (bytes_sent <= 0) {

-        pj_status_t rc = -bytes_sent;

-        if (rc != send_rec->last_err) {

-            send_rec->last_err = rc;

-            app_perror("...send error(2)", rc);

-        }

-    }

-

-    send_rec->is_pending = 0;

-    on_read_complete(key, &send_rec->peer->op_key_, 0);

-}

-

-static int worker_thread(void *arg)

-{

-    pj_ioqueue_t *ioqueue = arg;

-    struct op_key read_op, write_op;

-    char recv_buf[512], send_buf[512];

-    pj_ssize_t length;

-    pj_status_t rc;

-

-    read_op.peer = &write_op;

-    read_op.is_pending = 0;

-    read_op.last_err = 0;

-    read_op.buffer = recv_buf;

-    read_op.size = sizeof(recv_buf);

-    read_op.addrlen = sizeof(read_op.addr);

-

-    write_op.peer = &read_op;

-    write_op.is_pending = 0;

-    write_op.last_err = 0;

-    write_op.buffer = send_buf;

-    write_op.size = sizeof(send_buf);

-

-    length = sizeof(recv_buf);

-    rc = pj_ioqueue_recvfrom(key, &read_op.op_key_, recv_buf, &length, 0,

-                             &read_op.addr, &read_op.addrlen);

-    if (rc == PJ_SUCCESS) {

-        read_op.is_pending = 1;

-        on_read_complete(key, &read_op.op_key_, length);

-    }

-    

-    for (;;) {

-        pj_time_val timeout;

-        timeout.sec = 0; timeout.msec = 10;

-        rc = pj_ioqueue_poll(ioqueue, &timeout);

-    }

-}

-

-int udp_echo_srv_ioqueue(void)

-{

-    pj_pool_t *pool;

-    pj_sock_t sock;

-    pj_ioqueue_t *ioqueue;

-    pj_ioqueue_callback callback;

-    int i;

-    pj_thread_t *thread[ECHO_SERVER_MAX_THREADS];

-    pj_status_t rc;

-

-    pj_memset(&callback, 0, sizeof(callback));

-    callback.on_read_complete = &on_read_complete;

-    callback.on_write_complete = &on_write_complete;

-

-    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);

-    if (!pool)

-        return -10;

-

-    rc = pj_ioqueue_create(pool, 2, &ioqueue);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...pj_ioqueue_create error", rc);

-        return -20;

-    }

-

-    rc = app_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, 

-                    ECHO_SERVER_START_PORT, &sock);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...app_socket error", rc);

-        return -30;

-    }

-

-    rc = pj_ioqueue_register_sock(pool, ioqueue, sock, NULL,

-                                  &callback, &key);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error registering socket", rc);

-        return -40;

-    }

-

-    rc = pj_atomic_create(pool, 0, &total_bytes);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...error creating atomic variable", rc);

-        return -45;

-    }

-

-    for (i=0; i<ECHO_SERVER_MAX_THREADS; ++i) {

-        rc = pj_thread_create(pool, NULL, &worker_thread, ioqueue,

-                              PJ_THREAD_DEFAULT_STACK_SIZE, 0,

-                              &thread[i]);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...create thread error", rc);

-            return -50;

-        }

-    }

-

-    echo_srv_common_loop(total_bytes);

-

-    return 0;

-}

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pjlib.h>
+#include "test.h"
+
+static pj_ioqueue_key_t *key;
+static pj_atomic_t *total_bytes;
+
+struct op_key
+{
+    pj_ioqueue_op_key_t  op_key_;
+    struct op_key       *peer;
+    char                *buffer;
+    pj_size_t            size;
+    int                  is_pending;
+    pj_status_t          last_err;
+    pj_sockaddr_in       addr;
+    int                  addrlen;
+};
+
+static void on_read_complete(pj_ioqueue_key_t *key, 
+                             pj_ioqueue_op_key_t *op_key, 
+                             pj_ssize_t bytes_received)
+{
+    pj_status_t rc;
+    struct op_key *recv_rec = (struct op_key *)op_key;
+
+    for (;;) {
+        struct op_key *send_rec = recv_rec->peer;
+        recv_rec->is_pending = 0;
+
+        if (bytes_received < 0) {
+            if (-bytes_received != recv_rec->last_err) {
+                recv_rec->last_err = -bytes_received;
+                app_perror("...error receiving data", -bytes_received);
+            }
+        } else if (bytes_received == 0) {
+            /* note: previous error, or write callback */
+        } else {
+            pj_atomic_add(total_bytes, bytes_received);
+
+            if (!send_rec->is_pending) {
+                pj_ssize_t sent = bytes_received;
+                pj_memcpy(send_rec->buffer, recv_rec->buffer, bytes_received);
+                pj_memcpy(&send_rec->addr, &recv_rec->addr, recv_rec->addrlen);
+                send_rec->addrlen = recv_rec->addrlen;
+                rc = pj_ioqueue_sendto(key, &send_rec->op_key_, 
+                                       send_rec->buffer, &sent, 0,
+                                       &send_rec->addr, send_rec->addrlen);
+                send_rec->is_pending = (rc==PJ_EPENDING);
+
+                if (rc!=PJ_SUCCESS && rc!=PJ_EPENDING) {
+                    app_perror("...send error(1)", rc);
+                }
+            }
+        }
+
+        if (!send_rec->is_pending) {
+            bytes_received = recv_rec->size;
+            rc = pj_ioqueue_recvfrom(key, &recv_rec->op_key_, 
+                                     recv_rec->buffer, &bytes_received, 0,
+                                     &recv_rec->addr, &recv_rec->addrlen);
+            recv_rec->is_pending = (rc==PJ_EPENDING);
+            if (rc == PJ_SUCCESS) {
+                /* fall through next loop. */
+            } else if (rc == PJ_EPENDING) {
+                /* quit callback. */
+                break;
+            } else {
+                /* error */
+                app_perror("...recv error", rc);
+                recv_rec->last_err = rc;
+
+                bytes_received = 0;
+                /* fall through next loop. */
+            }
+        } else {
+            /* recv will be done when write completion callback is called. */
+            break;
+        }
+    }
+}
+
+static void on_write_complete(pj_ioqueue_key_t *key, 
+                              pj_ioqueue_op_key_t *op_key, 
+                              pj_ssize_t bytes_sent)
+{
+    struct op_key *send_rec = (struct op_key*)op_key;
+
+    if (bytes_sent <= 0) {
+        pj_status_t rc = -bytes_sent;
+        if (rc != send_rec->last_err) {
+            send_rec->last_err = rc;
+            app_perror("...send error(2)", rc);
+        }
+    }
+
+    send_rec->is_pending = 0;
+    on_read_complete(key, &send_rec->peer->op_key_, 0);
+}
+
+static int worker_thread(void *arg)
+{
+    pj_ioqueue_t *ioqueue = arg;
+    struct op_key read_op, write_op;
+    char recv_buf[512], send_buf[512];
+    pj_ssize_t length;
+    pj_status_t rc;
+
+    read_op.peer = &write_op;
+    read_op.is_pending = 0;
+    read_op.last_err = 0;
+    read_op.buffer = recv_buf;
+    read_op.size = sizeof(recv_buf);
+    read_op.addrlen = sizeof(read_op.addr);
+
+    write_op.peer = &read_op;
+    write_op.is_pending = 0;
+    write_op.last_err = 0;
+    write_op.buffer = send_buf;
+    write_op.size = sizeof(send_buf);
+
+    length = sizeof(recv_buf);
+    rc = pj_ioqueue_recvfrom(key, &read_op.op_key_, recv_buf, &length, 0,
+                             &read_op.addr, &read_op.addrlen);
+    if (rc == PJ_SUCCESS) {
+        read_op.is_pending = 1;
+        on_read_complete(key, &read_op.op_key_, length);
+    }
+    
+    for (;;) {
+        pj_time_val timeout;
+        timeout.sec = 0; timeout.msec = 10;
+        rc = pj_ioqueue_poll(ioqueue, &timeout);
+    }
+}
+
+int udp_echo_srv_ioqueue(void)
+{
+    pj_pool_t *pool;
+    pj_sock_t sock;
+    pj_ioqueue_t *ioqueue;
+    pj_ioqueue_callback callback;
+    int i;
+    pj_thread_t *thread[ECHO_SERVER_MAX_THREADS];
+    pj_status_t rc;
+
+    pj_memset(&callback, 0, sizeof(callback));
+    callback.on_read_complete = &on_read_complete;
+    callback.on_write_complete = &on_write_complete;
+
+    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
+    if (!pool)
+        return -10;
+
+    rc = pj_ioqueue_create(pool, 2, &ioqueue);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...pj_ioqueue_create error", rc);
+        return -20;
+    }
+
+    rc = app_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, 
+                    ECHO_SERVER_START_PORT, &sock);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...app_socket error", rc);
+        return -30;
+    }
+
+    rc = pj_ioqueue_register_sock(pool, ioqueue, sock, NULL,
+                                  &callback, &key);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error registering socket", rc);
+        return -40;
+    }
+
+    rc = pj_atomic_create(pool, 0, &total_bytes);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...error creating atomic variable", rc);
+        return -45;
+    }
+
+    for (i=0; i<ECHO_SERVER_MAX_THREADS; ++i) {
+        rc = pj_thread_create(pool, NULL, &worker_thread, ioqueue,
+                              PJ_THREAD_DEFAULT_STACK_SIZE, 0,
+                              &thread[i]);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...create thread error", rc);
+            return -50;
+        }
+    }
+
+    echo_srv_common_loop(total_bytes);
+
+    return 0;
+}
diff --git a/pjlib/src/pjlib-test/udp_echo_srv_sync.c b/pjlib/src/pjlib-test/udp_echo_srv_sync.c
index 312fa8c..34633de 100644
--- a/pjlib/src/pjlib-test/udp_echo_srv_sync.c
+++ b/pjlib/src/pjlib-test/udp_echo_srv_sync.c
@@ -1,163 +1,163 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pjlib.h>

-

-static pj_atomic_t *total_bytes;

-

-static int worker_thread(void *arg)

-{

-    pj_sock_t    sock = (pj_sock_t)arg;

-    char         buf[512];

-    pj_status_t  last_recv_err = PJ_SUCCESS, last_write_err = PJ_SUCCESS;

-

-    for (;;) {

-        pj_ssize_t len;

-        pj_status_t rc;

-        pj_sockaddr_in addr;

-        int addrlen;

-

-        len = sizeof(buf);

-        addrlen = sizeof(addr);

-        rc = pj_sock_recvfrom(sock, buf, &len, 0, &addr, &addrlen);

-        if (rc != 0) {

-            if (rc != last_recv_err) {

-                app_perror("...recv error", rc);

-                last_recv_err = rc;

-            }

-            continue;

-        }

-

-        pj_atomic_add(total_bytes, len);

-

-        rc = pj_sock_sendto(sock, buf, &len, 0, &addr, addrlen);

-        if (rc != PJ_SUCCESS) {

-            if (rc != last_write_err) {

-                app_perror("...send error", rc);

-                last_write_err = rc;

-            }

-            continue;

-        }

-    }

-}

-

-

-int echo_srv_sync(void)

-{

-    pj_pool_t *pool;

-    pj_sock_t sock;

-    pj_thread_t *thread[ECHO_SERVER_MAX_THREADS];

-    pj_status_t rc;

-    int i;

-

-    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);

-    if (!pool)

-        return -5;

-

-    rc = pj_atomic_create(pool, 0, &total_bytes);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...unable to create atomic_var", rc);

-        return -6;

-    }

-

-    rc = app_socket(PJ_AF_INET, PJ_SOCK_DGRAM,0, ECHO_SERVER_START_PORT, &sock);

-    if (rc != PJ_SUCCESS) {

-        app_perror("...socket error", rc);

-        return -10;

-    }

-

-    for (i=0; i<ECHO_SERVER_MAX_THREADS; ++i) {

-        rc = pj_thread_create(pool, NULL, &worker_thread, (void*)sock,

-                              PJ_THREAD_DEFAULT_STACK_SIZE, 0,

-                              &thread[i]);

-        if (rc != PJ_SUCCESS) {

-            app_perror("...unable to create thread", rc);

-            return -20;

-        }

-    }

-

-    PJ_LOG(3,("", "...UDP echo server running with %d threads at port %d",

-                  ECHO_SERVER_MAX_THREADS, ECHO_SERVER_START_PORT));

-    PJ_LOG(3,("", "...Press Ctrl-C to abort"));

-

-    echo_srv_common_loop(total_bytes);

-    return 0;

-}

-

-

-int echo_srv_common_loop(pj_atomic_t *bytes_counter)

-{

-    pj_highprec_t last_received, avg_bw, highest_bw;

-    pj_time_val last_print;

-    unsigned count;

-    const char *ioqueue_name;

-

-    last_received = 0;

-    pj_gettimeofday(&last_print);

-    avg_bw = highest_bw = 0;

-    count = 0;

-

-    ioqueue_name = pj_ioqueue_name();

-

-    for (;;) {

-        pj_highprec_t received, cur_received, bw;

-        unsigned msec;

-        pj_time_val now, duration;

-

-        pj_thread_sleep(1000);

-

-        received = cur_received = pj_atomic_get(bytes_counter);

-        cur_received = cur_received - last_received;

-

-        pj_gettimeofday(&now);

-        duration = now;

-        PJ_TIME_VAL_SUB(duration, last_print);

-        msec = PJ_TIME_VAL_MSEC(duration);

-        

-        bw = cur_received;

-        pj_highprec_mul(bw, 1000);

-        pj_highprec_div(bw, msec);

-

-        last_print = now;

-        last_received = received;

-

-        avg_bw = avg_bw + bw;

-        count++;

-

-        PJ_LOG(3,("", "%s UDP (%d threads): %u KB/s (avg=%u KB/s) %s", 

-		  ioqueue_name,

-                  ECHO_SERVER_MAX_THREADS, 

-                  (unsigned)(bw / 1000),

-                  (unsigned)(avg_bw / count / 1000),

-                  (count==20 ? "<ses avg>" : "")));

-

-        if (count==20) {

-            if (avg_bw/count > highest_bw)

-                highest_bw = avg_bw/count;

-

-            count = 0;

-            avg_bw = 0;

-

-            PJ_LOG(3,("", "Highest average bandwidth=%u KB/s",

-                          (unsigned)(highest_bw/1000)));

-        }

-    }

-}

-

-

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib.h>
+
+static pj_atomic_t *total_bytes;
+
+static int worker_thread(void *arg)
+{
+    pj_sock_t    sock = (pj_sock_t)arg;
+    char         buf[512];
+    pj_status_t  last_recv_err = PJ_SUCCESS, last_write_err = PJ_SUCCESS;
+
+    for (;;) {
+        pj_ssize_t len;
+        pj_status_t rc;
+        pj_sockaddr_in addr;
+        int addrlen;
+
+        len = sizeof(buf);
+        addrlen = sizeof(addr);
+        rc = pj_sock_recvfrom(sock, buf, &len, 0, &addr, &addrlen);
+        if (rc != 0) {
+            if (rc != last_recv_err) {
+                app_perror("...recv error", rc);
+                last_recv_err = rc;
+            }
+            continue;
+        }
+
+        pj_atomic_add(total_bytes, len);
+
+        rc = pj_sock_sendto(sock, buf, &len, 0, &addr, addrlen);
+        if (rc != PJ_SUCCESS) {
+            if (rc != last_write_err) {
+                app_perror("...send error", rc);
+                last_write_err = rc;
+            }
+            continue;
+        }
+    }
+}
+
+
+int echo_srv_sync(void)
+{
+    pj_pool_t *pool;
+    pj_sock_t sock;
+    pj_thread_t *thread[ECHO_SERVER_MAX_THREADS];
+    pj_status_t rc;
+    int i;
+
+    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
+    if (!pool)
+        return -5;
+
+    rc = pj_atomic_create(pool, 0, &total_bytes);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...unable to create atomic_var", rc);
+        return -6;
+    }
+
+    rc = app_socket(PJ_AF_INET, PJ_SOCK_DGRAM,0, ECHO_SERVER_START_PORT, &sock);
+    if (rc != PJ_SUCCESS) {
+        app_perror("...socket error", rc);
+        return -10;
+    }
+
+    for (i=0; i<ECHO_SERVER_MAX_THREADS; ++i) {
+        rc = pj_thread_create(pool, NULL, &worker_thread, (void*)sock,
+                              PJ_THREAD_DEFAULT_STACK_SIZE, 0,
+                              &thread[i]);
+        if (rc != PJ_SUCCESS) {
+            app_perror("...unable to create thread", rc);
+            return -20;
+        }
+    }
+
+    PJ_LOG(3,("", "...UDP echo server running with %d threads at port %d",
+                  ECHO_SERVER_MAX_THREADS, ECHO_SERVER_START_PORT));
+    PJ_LOG(3,("", "...Press Ctrl-C to abort"));
+
+    echo_srv_common_loop(total_bytes);
+    return 0;
+}
+
+
+int echo_srv_common_loop(pj_atomic_t *bytes_counter)
+{
+    pj_highprec_t last_received, avg_bw, highest_bw;
+    pj_time_val last_print;
+    unsigned count;
+    const char *ioqueue_name;
+
+    last_received = 0;
+    pj_gettimeofday(&last_print);
+    avg_bw = highest_bw = 0;
+    count = 0;
+
+    ioqueue_name = pj_ioqueue_name();
+
+    for (;;) {
+        pj_highprec_t received, cur_received, bw;
+        unsigned msec;
+        pj_time_val now, duration;
+
+        pj_thread_sleep(1000);
+
+        received = cur_received = pj_atomic_get(bytes_counter);
+        cur_received = cur_received - last_received;
+
+        pj_gettimeofday(&now);
+        duration = now;
+        PJ_TIME_VAL_SUB(duration, last_print);
+        msec = PJ_TIME_VAL_MSEC(duration);
+        
+        bw = cur_received;
+        pj_highprec_mul(bw, 1000);
+        pj_highprec_div(bw, msec);
+
+        last_print = now;
+        last_received = received;
+
+        avg_bw = avg_bw + bw;
+        count++;
+
+        PJ_LOG(3,("", "%s UDP (%d threads): %u KB/s (avg=%u KB/s) %s", 
+		  ioqueue_name,
+                  ECHO_SERVER_MAX_THREADS, 
+                  (unsigned)(bw / 1000),
+                  (unsigned)(avg_bw / count / 1000),
+                  (count==20 ? "<ses avg>" : "")));
+
+        if (count==20) {
+            if (avg_bw/count > highest_bw)
+                highest_bw = avg_bw/count;
+
+            count = 0;
+            avg_bw = 0;
+
+            PJ_LOG(3,("", "Highest average bandwidth=%u KB/s",
+                          (unsigned)(highest_bw/1000)));
+        }
+    }
+}
+
+
diff --git a/pjlib/src/pjlib-test/util.c b/pjlib/src/pjlib-test/util.c
index b4d3a3f..d5cded2 100644
--- a/pjlib/src/pjlib-test/util.c
+++ b/pjlib/src/pjlib-test/util.c
@@ -1,131 +1,131 @@
-/* $Id$ */

-/* 

- * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License as published by

- * the Free Software Foundation; either version 2 of the License, or

- * (at your option) any later version.

- *

- * This program 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 General Public License for more details.

- *

- * You should have received a copy of the GNU General Public License

- * along with this program; if not, write to the Free Software

- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

- */

-#include "test.h"

-#include <pjlib.h>

-

-void app_perror(const char *msg, pj_status_t rc)

-{

-    char errbuf[256];

-

-    PJ_CHECK_STACK();

-

-    pj_strerror(rc, errbuf, sizeof(errbuf));

-    PJ_LOG(1,("test", "%s: [pj_status_t=%d] %s", msg, rc, errbuf));

-}

-

-#define SERVER 0

-#define CLIENT 1

-

-pj_status_t app_socket(int family, int type, int proto, int port,

-                       pj_sock_t *ptr_sock)

-{

-    pj_sockaddr_in addr;

-    pj_sock_t sock;

-    pj_status_t rc;

-

-    rc = pj_sock_socket(family, type, proto, &sock);

-    if (rc != PJ_SUCCESS)

-        return rc;

-

-    pj_memset(&addr, 0, sizeof(addr));

-    addr.sin_family = (pj_uint16_t)family;

-    addr.sin_port = (short)(port!=-1 ? pj_htons((pj_uint16_t)port) : 0);

-    rc = pj_sock_bind(sock, &addr, sizeof(addr));

-    if (rc != PJ_SUCCESS)

-        return rc;

-    

-    if (type == PJ_SOCK_STREAM) {

-        rc = pj_sock_listen(sock, 5);

-        if (rc != PJ_SUCCESS)

-            return rc;

-    }

-

-    *ptr_sock = sock;

-    return PJ_SUCCESS;

-}

-

-pj_status_t app_socketpair(int family, int type, int protocol,

-                           pj_sock_t *serverfd, pj_sock_t *clientfd)

-{

-    int i;

-    static unsigned short port = 11000;

-    pj_sockaddr_in addr;

-    pj_str_t s;

-    pj_status_t rc = 0;

-    pj_sock_t sock[2];

-

-    /* Create both sockets. */

-    for (i=0; i<2; ++i) {

-        rc = pj_sock_socket(family, type, protocol, &sock[i]);

-        if (rc != PJ_SUCCESS) {

-            if (i==1)

-                pj_sock_close(sock[0]);

-            return rc;

-        }

-    }

-

-    /* Retry bind */

-    pj_memset(&addr, 0, sizeof(addr));

-    addr.sin_family = PJ_AF_INET;

-    for (i=0; i<5; ++i) {

-        addr.sin_port = pj_htons(port++);

-        rc = pj_sock_bind(sock[SERVER], &addr, sizeof(addr));

-        if (rc == PJ_SUCCESS)

-            break;

-    }

-

-    if (rc != PJ_SUCCESS)

-        goto on_error;

-

-    /* For TCP, listen the socket. */

-    if (type == PJ_SOCK_STREAM) {

-        rc = pj_sock_listen(sock[SERVER], PJ_SOMAXCONN);

-        if (rc != PJ_SUCCESS)

-            goto on_error;

-    }

-

-    /* Connect client socket. */

-    addr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));

-    rc = pj_sock_connect(sock[CLIENT], &addr, sizeof(addr));

-    if (rc != PJ_SUCCESS)

-        goto on_error;

-

-    /* For TCP, must accept(), and get the new socket. */

-    if (type == PJ_SOCK_STREAM) {

-        pj_sock_t newserver;

-

-        rc = pj_sock_accept(sock[SERVER], &newserver, NULL, NULL);

-        if (rc != PJ_SUCCESS)

-            goto on_error;

-

-        /* Replace server socket with new socket. */

-        pj_sock_close(sock[SERVER]);

-        sock[SERVER] = newserver;

-    }

-

-    *serverfd = sock[SERVER];

-    *clientfd = sock[CLIENT];

-

-    return rc;

-

-on_error:

-    for (i=0; i<2; ++i)

-        pj_sock_close(sock[i]);

-    return rc;

-}

+/* $Id$ */
+/* 
+ * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib.h>
+
+void app_perror(const char *msg, pj_status_t rc)
+{
+    char errbuf[256];
+
+    PJ_CHECK_STACK();
+
+    pj_strerror(rc, errbuf, sizeof(errbuf));
+    PJ_LOG(1,("test", "%s: [pj_status_t=%d] %s", msg, rc, errbuf));
+}
+
+#define SERVER 0
+#define CLIENT 1
+
+pj_status_t app_socket(int family, int type, int proto, int port,
+                       pj_sock_t *ptr_sock)
+{
+    pj_sockaddr_in addr;
+    pj_sock_t sock;
+    pj_status_t rc;
+
+    rc = pj_sock_socket(family, type, proto, &sock);
+    if (rc != PJ_SUCCESS)
+        return rc;
+
+    pj_memset(&addr, 0, sizeof(addr));
+    addr.sin_family = (pj_uint16_t)family;
+    addr.sin_port = (short)(port!=-1 ? pj_htons((pj_uint16_t)port) : 0);
+    rc = pj_sock_bind(sock, &addr, sizeof(addr));
+    if (rc != PJ_SUCCESS)
+        return rc;
+    
+    if (type == PJ_SOCK_STREAM) {
+        rc = pj_sock_listen(sock, 5);
+        if (rc != PJ_SUCCESS)
+            return rc;
+    }
+
+    *ptr_sock = sock;
+    return PJ_SUCCESS;
+}
+
+pj_status_t app_socketpair(int family, int type, int protocol,
+                           pj_sock_t *serverfd, pj_sock_t *clientfd)
+{
+    int i;
+    static unsigned short port = 11000;
+    pj_sockaddr_in addr;
+    pj_str_t s;
+    pj_status_t rc = 0;
+    pj_sock_t sock[2];
+
+    /* Create both sockets. */
+    for (i=0; i<2; ++i) {
+        rc = pj_sock_socket(family, type, protocol, &sock[i]);
+        if (rc != PJ_SUCCESS) {
+            if (i==1)
+                pj_sock_close(sock[0]);
+            return rc;
+        }
+    }
+
+    /* Retry bind */
+    pj_memset(&addr, 0, sizeof(addr));
+    addr.sin_family = PJ_AF_INET;
+    for (i=0; i<5; ++i) {
+        addr.sin_port = pj_htons(port++);
+        rc = pj_sock_bind(sock[SERVER], &addr, sizeof(addr));
+        if (rc == PJ_SUCCESS)
+            break;
+    }
+
+    if (rc != PJ_SUCCESS)
+        goto on_error;
+
+    /* For TCP, listen the socket. */
+    if (type == PJ_SOCK_STREAM) {
+        rc = pj_sock_listen(sock[SERVER], PJ_SOMAXCONN);
+        if (rc != PJ_SUCCESS)
+            goto on_error;
+    }
+
+    /* Connect client socket. */
+    addr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1"));
+    rc = pj_sock_connect(sock[CLIENT], &addr, sizeof(addr));
+    if (rc != PJ_SUCCESS)
+        goto on_error;
+
+    /* For TCP, must accept(), and get the new socket. */
+    if (type == PJ_SOCK_STREAM) {
+        pj_sock_t newserver;
+
+        rc = pj_sock_accept(sock[SERVER], &newserver, NULL, NULL);
+        if (rc != PJ_SUCCESS)
+            goto on_error;
+
+        /* Replace server socket with new socket. */
+        pj_sock_close(sock[SERVER]);
+        sock[SERVER] = newserver;
+    }
+
+    *serverfd = sock[SERVER];
+    *clientfd = sock[CLIENT];
+
+    return rc;
+
+on_error:
+    for (i=0; i<2; ++i)
+        pj_sock_close(sock[i]);
+    return rc;
+}