summaryrefslogtreecommitdiff
path: root/pjlib/src
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2005-11-21 01:55:47 +0000
committerBenny Prijono <bennylp@teluu.com>2005-11-21 01:55:47 +0000
commit5f1de1bbb341ea1dc1d27d9bf35764b643ef904a (patch)
treed18b0365b69b8b488a0b2b2bd715e9f14f77b505 /pjlib/src
parent9f4da35e676737f830a90a18de08440cf0f6cdf9 (diff)
Set svn:eol-style property
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@65 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjlib/src')
-rw-r--r--pjlib/src/pj/addr_resolv_linux_kernel.c50
-rw-r--r--pjlib/src/pj/addr_resolv_sock.c102
-rw-r--r--pjlib/src/pj/array.c140
-rw-r--r--pjlib/src/pj/compat/sigjmp.c78
-rw-r--r--pjlib/src/pj/compat/string.c88
-rw-r--r--pjlib/src/pjlib++-test/main.cpp122
-rw-r--r--pjlib/src/pjlib-samples/except.c170
-rw-r--r--pjlib/src/pjlib-samples/list.c142
-rw-r--r--pjlib/src/pjlib-samples/log.c84
-rw-r--r--pjlib/src/pjlib-test/atomic.c216
-rw-r--r--pjlib/src/pjlib-test/echo_clt.c536
-rw-r--r--pjlib/src/pjlib-test/errno.c324
-rw-r--r--pjlib/src/pjlib-test/exception.c354
-rw-r--r--pjlib/src/pjlib-test/fifobuf.c232
-rw-r--r--pjlib/src/pjlib-test/file.c424
-rw-r--r--pjlib/src/pjlib-test/ioq_perf.c1004
-rw-r--r--pjlib/src/pjlib-test/ioq_tcp.c1080
-rw-r--r--pjlib/src/pjlib-test/ioq_udp.c1326
-rw-r--r--pjlib/src/pjlib-test/list.c450
-rw-r--r--pjlib/src/pjlib-test/main.c186
-rw-r--r--pjlib/src/pjlib-test/main_mod.c78
-rw-r--r--pjlib/src/pjlib-test/mutex.c348
-rw-r--r--pjlib/src/pjlib-test/os.c38
-rw-r--r--pjlib/src/pjlib-test/pool.c344
-rw-r--r--pjlib/src/pjlib-test/pool_perf.c280
-rw-r--r--pjlib/src/pjlib-test/rand.c106
-rw-r--r--pjlib/src/pjlib-test/rbtree.c334
-rw-r--r--pjlib/src/pjlib-test/select.c434
-rw-r--r--pjlib/src/pjlib-test/sleep.c400
-rw-r--r--pjlib/src/pjlib-test/sock.c912
-rw-r--r--pjlib/src/pjlib-test/sock_perf.c366
-rw-r--r--pjlib/src/pjlib-test/string.c348
-rw-r--r--pjlib/src/pjlib-test/test.c398
-rw-r--r--pjlib/src/pjlib-test/test.h222
-rw-r--r--pjlib/src/pjlib-test/thread.c578
-rw-r--r--pjlib/src/pjlib-test/timer.c372
-rw-r--r--pjlib/src/pjlib-test/timestamp.c286
-rw-r--r--pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c422
-rw-r--r--pjlib/src/pjlib-test/udp_echo_srv_sync.c326
-rw-r--r--pjlib/src/pjlib-test/util.c262
40 files changed, 6981 insertions, 6981 deletions
diff --git a/pjlib/src/pj/addr_resolv_linux_kernel.c b/pjlib/src/pj/addr_resolv_linux_kernel.c
index fe70acbb..d6a4dcc3 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 e4493b23..9b9eb6dc 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 59854a1c..2afe8fe6 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 90161763..6b071547 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 77fb1a57..bb2362ca 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 86858a1d..dc3b17ed 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 6611a9da..3bbfa544 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 6f089dac..72e514e6 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 e6712641..dffcb72e 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 2f6acc5e..a7fbe60f 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 a9d8183c..2453d120 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 1a2560c2..999f3525 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 b09ba11c..ef4bf4a2 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 03917de6..753ae251 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 ffa72efd..d22c3956 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 b10decc3..3a8de8e1 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 ade37ec2..c60d614f 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 1e3b6dc8..7db2a8eb 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 4777a9fa..7aa638b0 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 89c0853c..fea4cd6f 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 2e7d8607..2dada340 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 29fabd4c..877712d7 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 2d1b2693..7f3c1614 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 b20e63a5..d48a3589 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 a7c8fba9..6bc6dcfb 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 33e81075..6edfbd21 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 588e58a7..dc10218d 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 44184730..ed2edd40 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 1af794e1..5732a165 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 2961b788..b8af3cd8 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 bb20f8a7..a3b46b98 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 7199c565..96a4ade1 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 5fb89afa..6a1342c9 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 4f3267b0..8571d9dd 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 68264ea8..2c7c41f7 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 2ae5520a..8b2ebe58 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 ec103514..67e47c11 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 2dec91c4..8ede493b 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 312fa8c6..34633de2 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 b4d3a3f6..d5cded20 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;
+}