summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-04-30 21:03:32 +0000
committerBenny Prijono <bennylp@teluu.com>2007-04-30 21:03:32 +0000
commit9bfdd11aac28c934ce580880837cce948d9be10a (patch)
treee0414666d0e0b7b7ac99adb0125acf7b988b8428
parent25830dbc54149caeb660f1f379e547ed9eb09159 (diff)
Initial Symbian integration to trunk for pjlib
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1235 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--build.symbian/00.bat4
-rw-r--r--build.symbian/01.bat5
-rw-r--r--build.symbian/bld.inf9
-rw-r--r--build.symbian/pjlib.mmp65
-rw-r--r--build.symbian/pjlib_test.mmp57
-rw-r--r--pjlib/include/pj/compat/cc_codew.h51
-rw-r--r--pjlib/include/pj/compat/cc_mwcc.h51
-rw-r--r--pjlib/include/pj/compat/os_symbian.h159
-rw-r--r--pjlib/include/pj/compat/setjmp.h3
-rw-r--r--pjlib/include/pj/compat/socket.h5
-rw-r--r--pjlib/include/pj/compat/string.h10
-rw-r--r--pjlib/include/pj/config.h10
-rw-r--r--pjlib/include/pj/config_site_sample.h2
-rw-r--r--pjlib/include/pj/except.h23
-rw-r--r--pjlib/include/pj/list_i.h2
-rw-r--r--pjlib/src/pj/addr_resolv_symbian.cpp147
-rw-r--r--pjlib/src/pj/array.c2
-rw-r--r--pjlib/src/pj/compat/string_compat.c72
-rw-r--r--pjlib/src/pj/errno.c8
-rw-r--r--pjlib/src/pj/exception_symbian.cpp154
-rw-r--r--pjlib/src/pj/fifobuf.c6
-rw-r--r--pjlib/src/pj/guid.c2
-rw-r--r--pjlib/src/pj/hash.c21
-rw-r--r--pjlib/src/pj/ioqueue_symbian.cpp812
-rw-r--r--pjlib/src/pj/lock.c4
-rw-r--r--pjlib/src/pj/log_writer_symbian_console.cpp43
-rw-r--r--pjlib/src/pj/os_core_symbian.cpp816
-rw-r--r--pjlib/src/pj/os_error_symbian.cpp171
-rw-r--r--pjlib/src/pj/os_rwmutex.c2
-rw-r--r--pjlib/src/pj/os_symbian.h302
-rw-r--r--pjlib/src/pj/pool.c4
-rw-r--r--pjlib/src/pj/pool_buf.c2
-rw-r--r--pjlib/src/pj/pool_caching.c8
-rw-r--r--pjlib/src/pj/pool_policy_new.cpp73
-rw-r--r--pjlib/src/pj/sock_select_symbian.cpp162
-rw-r--r--pjlib/src/pj/sock_symbian.cpp931
-rw-r--r--pjlib/src/pj/timer.c14
-rw-r--r--pjlib/src/pj/unicode_symbian.cpp69
-rw-r--r--pjlib/src/pjlib-test/ioq_perf.c17
-rw-r--r--pjlib/src/pjlib-test/ioq_udp.c7
-rw-r--r--pjlib/src/pjlib-test/ioq_unreg.c7
-rw-r--r--pjlib/src/pjlib-test/main_symbian.cpp193
-rw-r--r--pjlib/src/pjlib-test/sock.c76
-rw-r--r--pjlib/src/pjlib-test/sock_perf.c4
-rw-r--r--pjlib/src/pjlib-test/string.c9
-rw-r--r--pjlib/src/pjlib-test/test.h34
-rw-r--r--pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c2
47 files changed, 4558 insertions, 72 deletions
diff --git a/build.symbian/00.bat b/build.symbian/00.bat
new file mode 100644
index 00000000..8f5b15a2
--- /dev/null
+++ b/build.symbian/00.bat
@@ -0,0 +1,4 @@
+rem set MWSym2Libraries=1
+set EPOCROOT=\Symbian\9.1\S60_3rd_MR_2\
+rem set EPOCROOT=\Symbian\UIQ3SDK\
+bldmake bldfiles
diff --git a/build.symbian/01.bat b/build.symbian/01.bat
new file mode 100644
index 00000000..df824732
--- /dev/null
+++ b/build.symbian/01.bat
@@ -0,0 +1,5 @@
+rem set MWSym2Libraries=1
+rem set MWSym2Libraries=\Symbian\9.1\S60_3rd\Epoc32\release\winscw\udeb
+
+set EPOCROOT=\Symbian\9.1\S60_3rd_MR_2\
+call abld build -v vs6 udeb
diff --git a/build.symbian/bld.inf b/build.symbian/bld.inf
new file mode 100644
index 00000000..91a4ead8
--- /dev/null
+++ b/build.symbian/bld.inf
@@ -0,0 +1,9 @@
+prj_mmpfiles
+pjlib.mmp
+//pjlib_util.mmp
+//pjsip.mmp
+//pjsip_simple.mmp
+//pjsdp.mmp
+//pjsip_ua.mmp
+//pjlib_test.mmp
+//sipstateless.mmp
diff --git a/build.symbian/pjlib.mmp b/build.symbian/pjlib.mmp
new file mode 100644
index 00000000..c3e689ab
--- /dev/null
+++ b/build.symbian/pjlib.mmp
@@ -0,0 +1,65 @@
+TARGET pjlib.lib
+TARGETTYPE lib
+UID 0x100039CE 0x10004299
+VENDORID 0x70000001
+
+SOURCEPATH ..\pjlib\src\pj
+
+OPTION CW -lang c++
+
+MACRO PJ_M_I386=1
+MACRO PJ_SYMBIAN=1
+MACRO PJ_EXPORTING
+
+//
+// Platform independent source
+//
+SOURCE array.c
+SOURCE config.c
+SOURCE ctype.c
+SOURCE errno.c
+SOURCE fifobuf.c
+SOURCE guid.c
+SOURCE hash.c
+SOURCE list.c
+SOURCE lock.c
+SOURCE string.c
+SOURCE log.c
+SOURCE os_time_common.c
+SOURCE pool.c
+SOURCE pool_buf.c
+SOURCE pool_caching.c
+SOURCE rand.c
+SOURCE rbtree.c
+SOURCE timer.c
+SOURCE types.c
+
+
+//
+// Platform dependent source
+//
+SOURCE addr_resolv_symbian.cpp
+SOURCE exception_symbian.cpp
+SOURCE file_access_unistd.c
+SOURCE file_io_ansi.c
+SOURCE guid_simple.c
+SOURCE ip_helper_generic.c
+SOURCE log_writer_symbian_console.cpp
+SOURCE os_core_symbian.cpp
+SOURCE os_error_symbian.cpp
+SOURCE os_timestamp_common.c
+SOURCE os_time_unix.c
+SOURCE os_timestamp_posix.c
+SOURCE pool_policy_new.cpp
+SOURCE compat\string_compat.c
+SOURCE sock_symbian.cpp
+SOURCE sock_select_symbian.cpp
+SOURCE ioqueue_symbian.cpp
+SOURCE unicode_symbian.cpp
+
+
+SYSTEMINCLUDE ..\pjlib\include
+
+SYSTEMINCLUDE \epoc32\include
+SYSTEMINCLUDE \epoc32\include\libc
+
diff --git a/build.symbian/pjlib_test.mmp b/build.symbian/pjlib_test.mmp
new file mode 100644
index 00000000..e4294b1a
--- /dev/null
+++ b/build.symbian/pjlib_test.mmp
@@ -0,0 +1,57 @@
+TARGET pjlib_test.exe
+TARGETTYPE exe
+UID 0x100039CE 0x10004299
+VENDORID 0x70000001
+
+SOURCEPATH ..\pjlib\src\pjlib-test
+
+MACRO PJ_M_I386=1
+MACRO PJ_SYMBIAN=1
+MACRO PJ_IMPORTING
+
+OPTION CW -lang c++
+
+// Test files
+
+SOURCE atomic.c
+SOURCE echo_clt.c
+SOURCE errno.c
+SOURCE exception.c
+SOURCE fifobuf.c
+SOURCE file.c
+SOURCE ioq_perf.c
+SOURCE ioq_tcp.c
+SOURCE ioq_udp.c
+SOURCE ioq_unreg.c
+SOURCE list.c
+SOURCE mutex.c
+SOURCE os.c
+SOURCE pool.c
+SOURCE pool_perf.c
+SOURCE rand.c
+SOURCE rbtree.c
+SOURCE select.c
+SOURCE sleep.c
+SOURCE sock.c
+SOURCE sock_perf.c
+SOURCE string.c
+SOURCE test.c
+SOURCE thread.c
+SOURCE timer.c
+SOURCE timestamp.c
+SOURCE udp_echo_srv_ioqueue.c
+SOURCE udp_echo_srv_sync.c
+SOURCE util.c
+
+SOURCE main_symbian.cpp
+
+
+SYSTEMINCLUDE ..\pjlib\include
+
+SYSTEMINCLUDE \epoc32\include
+SYSTEMINCLUDE \epoc32\include\libc
+
+LIBRARY pjlib.lib esock.lib insock.lib charconv.lib euser.lib estlib.lib eexe.lib
+STATICLIBRARY ecrt0.lib
+CAPABILITY None
+
diff --git a/pjlib/include/pj/compat/cc_codew.h b/pjlib/include/pj/compat/cc_codew.h
new file mode 100644
index 00000000..cad9d0c5
--- /dev/null
+++ b/pjlib/include/pj/compat/cc_codew.h
@@ -0,0 +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
+ */
+#ifndef __PJ_COMPAT_CC_GCC_H__
+#define __PJ_COMPAT_CC_GCC_H__
+
+/**
+ * @file cc_codew.h
+ * @brief Describes MetroWerks Code Warrior compiler specifics.
+ */
+
+#ifndef __MWERKS__
+# error "This file is only for Code Warrior!"
+#endif
+
+#define PJ_CC_NAME "codewarrior"
+#define PJ_CC_VER_1 ((__MWERKS__ & 0xF000) >> 12)
+#define PJ_CC_VER_2 ((__MWERKS__ & 0x0F00) >> 8)
+#define PJ_CC_VER_3 ((__MWERKS__ & 0xFF))
+
+
+#define PJ_INLINE_SPECIFIER static inline
+#define PJ_THREAD_FUNC
+#define PJ_NORETURN
+#define PJ_ATTR_NORETURN
+
+#define PJ_HAS_INT64 1
+
+typedef long long pj_int64_t;
+typedef unsigned long long pj_uint64_t;
+
+#define PJ_INT64_FMT "L"
+
+
+#endif /* __PJ_COMPAT_CC_GCC_H__ */
+
diff --git a/pjlib/include/pj/compat/cc_mwcc.h b/pjlib/include/pj/compat/cc_mwcc.h
new file mode 100644
index 00000000..e22e9fb7
--- /dev/null
+++ b/pjlib/include/pj/compat/cc_mwcc.h
@@ -0,0 +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
+ */
+#ifndef __PJ_COMPAT_CC_MWCC_H__
+#define __PJ_COMPAT_CC_MWCC_H__
+
+/**
+ * @file cc_mwcc.h
+ * @brief Describes MWCC compiler specifics.
+ */
+
+#ifndef __CW32__
+# error "This file is only for mwcc!"
+#endif
+
+#define PJ_CC_NAME "mwcc32sym"
+#define PJ_CC_VER_1 1
+#define PJ_CC_VER_2 0
+#define PJ_CC_VER_3 0
+
+
+#define PJ_INLINE_SPECIFIER static inline
+#define PJ_THREAD_FUNC
+#define PJ_NORETURN
+#define PJ_ATTR_NORETURN __attribute__ ((noreturn))
+
+#define PJ_HAS_INT64 1
+
+typedef long long pj_int64_t;
+typedef unsigned long long pj_uint64_t;
+
+#define PJ_INT64_FMT "L"
+
+
+#endif /* __PJ_COMPAT_CC_MWCC_H__ */
+
diff --git a/pjlib/include/pj/compat/os_symbian.h b/pjlib/include/pj/compat/os_symbian.h
new file mode 100644
index 00000000..51d78eb6
--- /dev/null
+++ b/pjlib/include/pj/compat/os_symbian.h
@@ -0,0 +1,159 @@
+/* $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 __PJ_COMPAT_OS_SYMBIAN_H__
+#define __PJ_COMPAT_OS_SYMBIAN_H__
+
+/**
+ * @file os_symbian.h
+ * @brief Describes Symbian operating system specifics.
+ */
+
+#define PJ_OS_NAME "symbian"
+
+#define PJ_HAS_ARPA_INET_H 1
+#define PJ_HAS_ASSERT_H 1
+#define PJ_HAS_CTYPE_H 1
+#define PJ_HAS_ERRNO_H 1
+#define PJ_HAS_LINUX_SOCKET_H 0
+#define PJ_HAS_MALLOC_H 0
+#define PJ_HAS_NETDB_H 1
+#define PJ_HAS_NETINET_IN_H 1
+#define PJ_HAS_SETJMP_H 1
+#define PJ_HAS_STDARG_H 1
+#define PJ_HAS_STDDEF_H 1
+#define PJ_HAS_STDIO_H 1
+#define PJ_HAS_STDLIB_H 1
+#define PJ_HAS_STRING_H 1
+#define PJ_HAS_NO_SNPRINTF 1
+#define PJ_HAS_SYS_IOCTL_H 1
+#define PJ_HAS_SYS_SELECT_H 0
+#define PJ_HAS_SYS_SOCKET_H 1
+#define PJ_HAS_SYS_TIME_H 1
+#define PJ_HAS_SYS_TIMEB_H 0
+#define PJ_HAS_SYS_TYPES_H 1
+#define PJ_HAS_TIME_H 1
+#define PJ_HAS_UNISTD_H 1
+
+#define PJ_HAS_MSWSOCK_H 0
+#define PJ_HAS_WINSOCK_H 0
+#define PJ_HAS_WINSOCK2_H 0
+
+#define PJ_SOCK_HAS_INET_ATON 0
+
+/* Set 1 if native sockaddr_in has sin_len member.
+ * Default: 0
+ */
+#define PJ_SOCKADDR_HAS_LEN 0
+/* Is errno a good way to retrieve OS errors?
+ */
+#define PJ_HAS_ERRNO_VAR 1
+
+/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
+ * the status of non-blocking connect() operation.
+ */
+#define PJ_HAS_SO_ERROR 1
+
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS 0
+
+/* This value specifies the value set in errno by the OS when a non-blocking
+ * socket recv() can not return immediate daata.
+ */
+#define PJ_BLOCKING_ERROR_VAL EAGAIN
+
+/* This value specifies the value set in errno by the OS when a non-blocking
+ * socket connect() can not get connected immediately.
+ */
+#define PJ_BLOCKING_CONNECT_ERROR_VAL EINPROGRESS
+
+/*
+ * We don't want to use threads in Symbian
+ */
+#define PJ_HAS_THREADS 0
+
+
+/*
+ * Declare __FD_SETSIZE now before including <linux*>.
+#define __FD_SETSIZE PJ_IOQUEUE_MAX_HANDLES
+ */
+
+#ifndef NULL
+# define NULL 0
+#endif
+
+
+/* Doesn't seem to allow more than this */
+#define PJ_IOQUEUE_MAX_HANDLES 8
+
+/*
+ * Override features.
+ */
+#define PJ_HAS_FLOATING_POINT 1
+#define PJ_HAS_MALLOC 0
+#define PJ_HAS_SEMAPHORE 1
+#define PJ_HAS_EVENT_OBJ 0
+#define PJ_HAS_HIGH_RES_TIMER 1
+#define PJ_OS_HAS_CHECK_STACK 0
+#define PJ_TERM_HAS_COLOR 0
+#define PJ_NATIVE_STRING_IS_UNICODE 0
+
+#define PJ_ATOMIC_VALUE_TYPE int
+#define PJ_THREAD_DESC_SIZE 128
+
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX 1
+
+/* If 1, pj_thread_create() should enforce the stack size when creating
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE 0
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK 0
+
+/* Missing socklen_t */
+#define PJ_HAS_SOCKLEN_T 1
+typedef unsigned int socklen_t;
+
+#include <e32def.h>
+
+#if defined(PJ_EXPORTING)
+# define PJ_EXPORT_IMPORT EXPORT_C
+#elif defined(PJ_IMPORTING)
+# define PJ_EXPORT_IMPORT IMPORT_C
+#else
+# error "Must define either PJ_EXPORTING or PJ_IMPORTING"
+#endif
+
+#endif /* __PJ_COMPAT_OS_SYMBIAN_H__ */
+
+
+
diff --git a/pjlib/include/pj/compat/setjmp.h b/pjlib/include/pj/compat/setjmp.h
index b33ce445..2c2e4693 100644
--- a/pjlib/include/pj/compat/setjmp.h
+++ b/pjlib/include/pj/compat/setjmp.h
@@ -82,6 +82,9 @@
# endif /* _ASM */
+#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
+ /* Symbian framework don't use setjmp/longjmp */
+
#else
# warning "setjmp()/longjmp() is not implemented"
typedef int pj_jmp_buf[1];
diff --git a/pjlib/include/pj/compat/socket.h b/pjlib/include/pj/compat/socket.h
index 52ad3f55..40c03455 100644
--- a/pjlib/include/pj/compat/socket.h
+++ b/pjlib/include/pj/compat/socket.h
@@ -87,6 +87,11 @@
# define OSERR_EINPROGRESS WSAEINPROGRESS
# define OSERR_ECONNRESET WSAECONNRESET
# define OSERR_ENOTCONN WSAENOTCONN
+#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
+# define OSERR_EWOULDBLOCK -1
+# define OSERR_EINPROGRESS -1
+# define OSERR_ECONNRESET -1
+# define OSERR_ENOTCONN -1
#else
# define OSERR_EWOULDBLOCK EWOULDBLOCK
# define OSERR_EINPROGRESS EINPROGRESS
diff --git a/pjlib/include/pj/compat/string.h b/pjlib/include/pj/compat/string.h
index 07ac4e2f..896615b4 100644
--- a/pjlib/include/pj/compat/string.h
+++ b/pjlib/include/pj/compat/string.h
@@ -72,6 +72,16 @@
#define pj_ansi_strncasecmp strncasecmp
#define pj_ansi_strnicmp strncasecmp
#define pj_ansi_sprintf sprintf
+
+#if defined(PJ_HAS_NO_SNPRINTF) && PJ_HAS_NO_SNPRINTF != 0
+# include <pj/types.h>
+# include <pj/compat/stdarg.h>
+ PJ_BEGIN_DECL
+ PJ_DECL(int) snprintf(char*s1, pj_size_t len, const char*s2, ...);
+ PJ_DECL(int) vsnprintf(char*s1, pj_size_t len, const char*s2, va_list arg);
+ PJ_END_DECL
+#endif
+
#define pj_ansi_snprintf snprintf
#define pj_ansi_vsprintf vsprintf
#define pj_ansi_vsnprintf vsnprintf
diff --git a/pjlib/include/pj/config.h b/pjlib/include/pj/config.h
index 951823ea..e6d4fd4c 100644
--- a/pjlib/include/pj/config.h
+++ b/pjlib/include/pj/config.h
@@ -31,6 +31,10 @@
# include <pj/compat/cc_msvc.h>
#elif defined(__GNUC__)
# include <pj/compat/cc_gcc.h>
+#elif defined(__CW32__)
+# include <pj/compat/cc_mwcc.h>
+#elif defined(__MWERKS__)
+# include <pj/compat/cc_codew.h>
#else
# error "Unknown compiler."
#endif
@@ -45,6 +49,12 @@
*/
# include <pj/compat/os_auto.h>
+#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
+ /*
+ * SymbianOS
+ */
+# include <pj/compat/os_symbian.h>
+
#elif defined(PJ_WIN32_WINCE) || defined(_WIN32_WCE) || defined(UNDER_CE)
/*
* Windows CE
diff --git a/pjlib/include/pj/config_site_sample.h b/pjlib/include/pj/config_site_sample.h
index efa7638e..f873dd56 100644
--- a/pjlib/include/pj/config_site_sample.h
+++ b/pjlib/include/pj/config_site_sample.h
@@ -65,7 +65,7 @@
# define PJSIP_UDP_SO_RCVBUF_SIZE (24*1024*1024)
# define PJ_DEBUG 0
# define PJSIP_SAFE_MODULE 0
-# define PJ_HAS_STRICMP_ALNUM 1
+# define PJ_HAS_STRICMP_ALNUM 0
# define PJ_HASH_USE_OWN_TOLOWER 1
# define PJSIP_UNESCAPE_IN_PLACE 1
diff --git a/pjlib/include/pj/except.h b/pjlib/include/pj/except.h
index a07eb220..2f1f9ddd 100644
--- a/pjlib/include/pj/except.h
+++ b/pjlib/include/pj/except.h
@@ -237,6 +237,29 @@ pj_throw_exception_(pj_exception_id_t id) PJ_ATTR_NORETURN
#define PJ_THROW(id) pj_throw_exception_(id)
#define PJ_GET_EXCEPTION() GetExceptionCode()
+
+#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
+/*****************************************************************************
+ **
+ ** IMPLEMENTATION OF EXCEPTION USING SYMBIAN LEAVE/TRAP FRAMEWORK
+ **
+ ****************************************************************************/
+
+class TPjException
+{
+public:
+ int code_;
+};
+
+#define PJ_USE_EXCEPTION
+#define PJ_TRY try
+//#define PJ_CATCH(id)
+#define PJ_CATCH_ANY catch (const TPjException & pj_excp_)
+#define PJ_END
+#define PJ_THROW(x_id) do { TPjException e; e.code_=x_id; throw e;} \
+ while (0)
+#define PJ_GET_EXCEPTION() pj_excp_.code_
+
#else
/*****************************************************************************
**
diff --git a/pjlib/include/pj/list_i.h b/pjlib/include/pj/list_i.h
index d8544a79..f0a628e1 100644
--- a/pjlib/include/pj/list_i.h
+++ b/pjlib/include/pj/list_i.h
@@ -128,7 +128,7 @@ PJ_IDEF(pj_size_t) pj_list_size(pj_list_type *list)
while (node != list) {
++count;
- node = node->next;
+ node = (pj_list*)node->next;
}
return count;
diff --git a/pjlib/src/pj/addr_resolv_symbian.cpp b/pjlib/src/pj/addr_resolv_symbian.cpp
new file mode 100644
index 00000000..c9a776c8
--- /dev/null
+++ b/pjlib/src/pj/addr_resolv_symbian.cpp
@@ -0,0 +1,147 @@
+/* $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/errno.h>
+#include <pj/string.h>
+#include <pj/unicode.h>
+
+#include "os_symbian.h"
+
+
+// PJLIB API: resolve hostname
+PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *name, pj_hostent *he)
+{
+ PJ_ASSERT_RETURN(name && he, PJ_EINVAL);
+
+ RHostResolver &resv = PjSymbianOS::Instance()->GetResolver();
+
+ // Convert name to Unicode
+ wchar_t name16[PJ_MAX_HOSTNAME];
+ pj_ansi_to_unicode(name->ptr, name->slen, name16, PJ_ARRAY_SIZE(name16));
+ TPtrC16 data(name16);
+
+ // Resolve!
+ TNameEntry nameEntry;
+ TRequestStatus reqStatus;
+
+ resv.GetByName(data, nameEntry, reqStatus);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus != KErrNone)
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+
+ // Get the resolved TInetAddr
+ // This doesn't work, see Martin email on 28/3/2007:
+ // const TNameRecord &rec = (const TNameRecord&) nameEntry;
+ // TInetAddr inetAddr(rec.iAddr);
+ TInetAddr inetAddr(nameEntry().iAddr);
+
+ //
+ // This where we keep static variables.
+ // These should be kept in TLS probably, to allow multiple threads
+ // to call pj_gethostbyname() without interfering each other.
+ // But again, we don't support threads in Symbian!
+ //
+ static char resolved_name[PJ_MAX_HOSTNAME];
+ static char *no_aliases[1];
+ static pj_in_addr *addr_list[2];
+ static pj_sockaddr_in resolved_addr;
+
+ // Convert the official address to ANSI.
+ pj_unicode_to_ansi(nameEntry().iName.Ptr(), nameEntry().iName.Length(),
+ resolved_name, sizeof(resolved_name));
+
+ // Convert IP address
+
+ PjSymbianOS::Addr2pj(inetAddr, resolved_addr);
+ addr_list[0] = &resolved_addr.sin_addr;
+
+ // Return hostent
+ he->h_name = resolved_name;
+ he->h_aliases = no_aliases;
+ he->h_addrtype = PJ_AF_INET;
+ he->h_length = 4;
+ he->h_addr_list = (char**) addr_list;
+
+ return PJ_SUCCESS;
+}
+
+
+/* Resolve the IP address of local machine */
+pj_status_t pj_gethostip(pj_in_addr *addr)
+{
+ const pj_str_t *hostname = pj_gethostname();
+ struct pj_hostent he;
+ pj_str_t cp;
+ pj_in_addr loopip;
+ pj_status_t status;
+
+ cp = pj_str("127.0.0.1");
+ loopip = pj_inet_addr(&cp);
+
+ /* Try with resolving local hostname first */
+ status = pj_gethostbyname(hostname, &he);
+ if (status == PJ_SUCCESS) {
+ *addr = *(pj_in_addr*)he.h_addr;
+ }
+
+
+ /* If we end up with 127.0.0.1 or 0.0.0.0, resolve the IP by getting
+ * the default interface to connect to some public host.
+ */
+ if (status!=PJ_SUCCESS || addr->s_addr == loopip.s_addr || !addr->s_addr) {
+ pj_sock_t fd;
+ pj_sockaddr_in a;
+ int len;
+
+ status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &fd);
+ if (status != PJ_SUCCESS) {
+ return status;
+ }
+
+ cp = pj_str("1.1.1.1");
+ pj_sockaddr_in_init(&a, &cp, 53);
+
+ status = pj_sock_connect(fd, &a, sizeof(a));
+ if (status != PJ_SUCCESS) {
+ pj_sock_close(fd);
+ return status;
+ }
+
+ len = sizeof(a);
+ status = pj_sock_getsockname(fd, &a, &len);
+ if (status != PJ_SUCCESS) {
+ pj_sock_close(fd);
+ return status;
+ }
+
+ pj_sock_close(fd);
+
+ *addr = a.sin_addr;
+
+ if (a.sin_addr.s_addr == 0)
+ return PJ_ENOTFOUND;
+ }
+
+ return status;
+}
+
+
+
diff --git a/pjlib/src/pj/array.c b/pjlib/src/pj/array.c
index 8d63868f..832afee7 100644
--- a/pjlib/src/pj/array.c
+++ b/pjlib/src/pj/array.c
@@ -55,7 +55,7 @@ PJ_DEF(pj_status_t) pj_array_find( const void *array,
void **result)
{
unsigned i;
- const char *char_array = array;
+ const char *char_array = (const char*)array;
for (i=0; i<count; ++i) {
if ( (*matching)(char_array) == PJ_SUCCESS) {
if (result) {
diff --git a/pjlib/src/pj/compat/string_compat.c b/pjlib/src/pj/compat/string_compat.c
new file mode 100644
index 00000000..28f13123
--- /dev/null
+++ b/pjlib/src/pj/compat/string_compat.c
@@ -0,0 +1,72 @@
+/* $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>
+
+#if defined(PJ_HAS_STRING_H) && PJ_HAS_STRING_H != 0
+/* Nothing to do */
+#else
+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;
+}
+#endif
+
+#if defined(PJ_HAS_NO_SNPRINTF) && PJ_HAS_NO_SNPRINTF != 0
+
+PJ_DEF(int) snprintf(char *s1, pj_size_t len, const char *s2, ...)
+{
+ int ret;
+ va_list arg;
+
+ PJ_UNUSED_ARG(len);
+
+ va_start(arg, s2);
+ ret = vsprintf(s1, s2, arg);
+ va_end(arg);
+
+ return ret;
+}
+
+PJ_DEF(int) vsnprintf(char *s1, pj_size_t len, const char *s2, va_list arg)
+{
+ PJ_UNUSED_ARG(len);
+ return vsprintf(s1,s2,arg);
+}
+
+#endif
+
diff --git a/pjlib/src/pj/errno.c b/pjlib/src/pj/errno.c
index 7745dfd2..f82c22d6 100644
--- a/pjlib/src/pj/errno.c
+++ b/pjlib/src/pj/errno.c
@@ -18,13 +18,17 @@
*/
#include <pj/errno.h>
#include <pj/string.h>
+#include <pj/compat/string.h>
#include <pj/assert.h>
/* Prototype for platform specific error message, which will be defined
* in separate file.
*/
-extern int platform_strerror( pj_os_err_type code,
- char *buf, pj_size_t bufsize );
+PJ_BEGIN_DECL
+
+ PJ_DECL(int) platform_strerror(pj_os_err_type code,
+ char *buf, pj_size_t bufsize );
+PJ_END_DECL
#define PJLIB_MAX_ERR_MSG_HANDLER 8
diff --git a/pjlib/src/pj/exception_symbian.cpp b/pjlib/src/pj/exception_symbian.cpp
new file mode 100644
index 00000000..f04045bf
--- /dev/null
+++ b/pjlib/src/pj/exception_symbian.cpp
@@ -0,0 +1,154 @@
+/* $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/os.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/errno.h>
+
+static long thread_local_id = -1;
+
+#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
+ static const char *exception_id_names[PJ_MAX_EXCEPTION_ID];
+#else
+ /*
+ * Start from 1 (not 0)!!!
+ * Exception 0 is reserved for normal path of setjmp()!!!
+ */
+ static int last_exception_id = 1;
+#endif /* PJ_HAS_EXCEPTION_NAMES */
+
+
+//#if !defined(PJ_EXCEPTION_USE_WIN32_SEH) || PJ_EXCEPTION_USE_WIN32_SEH==0
+#if 0
+PJ_DEF(void) pj_throw_exception_(int exception_id)
+{
+ struct pj_exception_state_t *handler;
+
+ handler = (pj_exception_state_t*)pj_thread_local_get(thread_local_id);
+ if (handler == NULL) {
+ PJ_LOG(1,("except.c", "!!!FATAL: unhandled exception %d!\n", exception_id));
+ pj_assert(handler != NULL);
+ /* This will crash the system! */
+ }
+ pj_longjmp(handler->state, exception_id);
+}
+
+PJ_DEF(void) pj_push_exception_handler_(struct pj_exception_state_t *rec)
+{
+ struct pj_exception_state_t *parent_handler = NULL;
+
+ if (thread_local_id == -1) {
+ pj_thread_local_alloc(&thread_local_id);
+ pj_assert(thread_local_id != -1);
+ }
+ parent_handler = (pj_exception_state_t*)pj_thread_local_get(thread_local_id);
+ rec->prev = parent_handler;
+ pj_thread_local_set(thread_local_id, rec);
+}
+
+PJ_DEF(void) pj_pop_exception_handler_(void)
+{
+ struct pj_exception_state_t *handler;
+
+ handler = (pj_exception_state_t*)pj_thread_local_get(thread_local_id);
+ pj_assert(handler != NULL);
+ pj_thread_local_set(thread_local_id, handler->prev);
+}
+#endif
+
+#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
+PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
+ pj_exception_id_t *id)
+{
+ unsigned i;
+
+ pj_enter_critical_section();
+
+ /*
+ * Start from 1 (not 0)!!!
+ * Exception 0 is reserved for normal path of setjmp()!!!
+ */
+ for (i=1; i<PJ_MAX_EXCEPTION_ID; ++i) {
+ if (exception_id_names[i] == NULL) {
+ exception_id_names[i] = name;
+ *id = i;
+ pj_leave_critical_section();
+ return PJ_SUCCESS;
+ }
+ }
+
+ pj_leave_critical_section();
+ return PJ_ETOOMANY;
+}
+
+PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
+{
+ /*
+ * Start from 1 (not 0)!!!
+ * Exception 0 is reserved for normal path of setjmp()!!!
+ */
+ PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, PJ_EINVAL);
+
+ pj_enter_critical_section();
+ exception_id_names[id] = NULL;
+ pj_leave_critical_section();
+
+ return PJ_SUCCESS;
+
+}
+
+PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
+{
+ /*
+ * Start from 1 (not 0)!!!
+ * Exception 0 is reserved for normal path of setjmp()!!!
+ */
+ PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, "<Invalid ID>");
+
+ if (exception_id_names[id] == NULL)
+ return "<Unallocated ID>";
+
+ return exception_id_names[id];
+}
+
+#else /* PJ_HAS_EXCEPTION_NAMES */
+PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
+ pj_exception_id_t *id)
+{
+ PJ_ASSERT_RETURN(last_exception_id < PJ_MAX_EXCEPTION_ID-1, PJ_ETOOMANY);
+
+ *id = last_exception_id++;
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
+{
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
+{
+ return "";
+}
+
+#endif /* PJ_HAS_EXCEPTION_NAMES */
+
+
+
diff --git a/pjlib/src/pj/fifobuf.c b/pjlib/src/pj/fifobuf.c
index 50b7cf36..08bf907a 100644
--- a/pjlib/src/pj/fifobuf.c
+++ b/pjlib/src/pj/fifobuf.c
@@ -34,7 +34,7 @@ pj_fifobuf_init (pj_fifobuf_t *fifobuf, void *buffer, unsigned size)
"fifobuf_init fifobuf=%p buffer=%p, size=%d",
fifobuf, buffer, size));
- fifobuf->first = buffer;
+ fifobuf->first = (char*)buffer;
fifobuf->last = fifobuf->first + size;
fifobuf->ubegin = fifobuf->uend = fifobuf->first;
fifobuf->full = 0;
@@ -118,7 +118,7 @@ pj_fifobuf_alloc (pj_fifobuf_t *fifobuf, unsigned size)
PJ_DEF(pj_status_t)
pj_fifobuf_unalloc (pj_fifobuf_t *fifobuf, void *buf)
{
- char *ptr = buf;
+ char *ptr = (char*)buf;
char *endptr;
unsigned sz;
@@ -149,7 +149,7 @@ pj_fifobuf_unalloc (pj_fifobuf_t *fifobuf, void *buf)
PJ_DEF(pj_status_t)
pj_fifobuf_free (pj_fifobuf_t *fifobuf, void *buf)
{
- char *ptr = buf;
+ char *ptr = (char*)buf;
char *end;
unsigned sz;
diff --git a/pjlib/src/pj/guid.c b/pjlib/src/pj/guid.c
index dd308d5a..30ac2b13 100644
--- a/pjlib/src/pj/guid.c
+++ b/pjlib/src/pj/guid.c
@@ -21,6 +21,6 @@
PJ_DEF(void) pj_create_unique_string(pj_pool_t *pool, pj_str_t *str)
{
- str->ptr = pj_pool_alloc(pool, PJ_GUID_STRING_LENGTH);
+ str->ptr = (char*)pj_pool_alloc(pool, PJ_GUID_STRING_LENGTH);
pj_generate_unique_string(str);
}
diff --git a/pjlib/src/pj/hash.c b/pjlib/src/pj/hash.c
index 5a97e5f1..5b3454d9 100644
--- a/pjlib/src/pj/hash.c
+++ b/pjlib/src/pj/hash.c
@@ -55,13 +55,13 @@ PJ_DEF(pj_uint32_t) pj_hash_calc(pj_uint32_t hash, const void *key,
PJ_CHECK_STACK();
if (keylen==PJ_HASH_KEY_STRING) {
- const unsigned char *p = key;
+ const pj_uint8_t *p = (const pj_uint8_t*)key;
for ( ; *p; ++p ) {
hash = (hash * PJ_HASH_MULTIPLIER) + *p;
}
} else {
- const unsigned char *p = key,
- *end = p + keylen;
+ const pj_uint8_t *p = (const pj_uint8_t*)key,
+ *end = p + keylen;
for ( ; p!=end; ++p) {
hash = (hash * PJ_HASH_MULTIPLIER) + *p;
}
@@ -103,7 +103,7 @@ PJ_DEF(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size)
/* Check that PJ_HASH_ENTRY_SIZE is correct. */
PJ_ASSERT_RETURN(sizeof(pj_hash_entry)==PJ_HASH_ENTRY_SIZE, NULL);
- h = pj_pool_alloc(pool, sizeof(pj_hash_table_t));
+ h = PJ_POOL_ALLOC_T(pool, pj_hash_table_t);
h->count = 0;
PJ_LOG( 6, ("hashtbl", "hash table %p created from pool %s", h, pj_pool_getobjname(pool)));
@@ -119,7 +119,8 @@ PJ_DEF(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size)
table_size -= 1;
h->rows = table_size;
- h->table = pj_pool_calloc(pool, table_size+1, sizeof(pj_hash_entry*));
+ h->table = (pj_hash_entry**)
+ pj_pool_calloc(pool, table_size+1, sizeof(pj_hash_entry*));
return h;
}
@@ -142,14 +143,14 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht,
*/
hash=0;
if (keylen==PJ_HASH_KEY_STRING) {
- const unsigned char *p = key;
+ const pj_uint8_t *p = (const pj_uint8_t*)key;
for ( ; *p; ++p ) {
hash = hash * PJ_HASH_MULTIPLIER + *p;
}
keylen = p - (const unsigned char*)key;
} else {
- const unsigned char *p = key,
- *end = p + keylen;
+ const pj_uint8_t *p = (const pj_uint8_t*)key,
+ *end = p + keylen;
for ( ; p!=end; ++p) {
hash = hash * PJ_HASH_MULTIPLIER + *p;
}
@@ -179,12 +180,12 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht,
* If entry_buf is specified, use it. Otherwise allocate from pool.
*/
if (entry_buf) {
- entry = entry_buf;
+ entry = (pj_hash_entry*)entry_buf;
} else {
/* Pool must be specified! */
PJ_ASSERT_RETURN(pool != NULL, NULL);
- entry = pj_pool_alloc(pool, sizeof(pj_hash_entry));
+ entry = PJ_POOL_ALLOC_T(pool, pj_hash_entry);
PJ_LOG(6, ("hashtbl",
"%p: New p_entry %p created, pool used=%u, cap=%u",
ht, entry, pj_pool_get_used_size(pool),
diff --git a/pjlib/src/pj/ioqueue_symbian.cpp b/pjlib/src/pj/ioqueue_symbian.cpp
new file mode 100644
index 00000000..50f33503
--- /dev/null
+++ b/pjlib/src/pj/ioqueue_symbian.cpp
@@ -0,0 +1,812 @@
+/* $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/ioqueue.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/list.h>
+#include <pj/lock.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+
+#include "os_symbian.h"
+
+class CIoqueueCallback;
+
+/*
+ * IO Queue structure.
+ */
+struct pj_ioqueue_t
+{
+ int eventCount;
+ CPjTimeoutTimer *timeoutTimer;
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Class to encapsulate asynchronous socket operation.
+//
+class CIoqueueCallback : public CActive
+{
+public:
+ static CIoqueueCallback* NewL(pj_ioqueue_t *ioqueue,
+ pj_ioqueue_key_t *key,
+ pj_sock_t sock,
+ const pj_ioqueue_callback *cb,
+ void *user_data);
+
+ //
+ // Start asynchronous recv() operation
+ //
+ pj_status_t StartRead(pj_ioqueue_op_key_t *op_key,
+ void *buf, pj_ssize_t *size, unsigned flags,
+ pj_sockaddr_t *addr, int *addrlen);
+
+ //
+ // Start asynchronous accept() operation.
+ //
+ pj_status_t StartAccept(pj_ioqueue_op_key_t *op_key,
+ pj_sock_t *new_sock,
+ pj_sockaddr_t *local,
+ pj_sockaddr_t *remote,
+ int *addrlen );
+
+ //
+ // Completion callback.
+ //
+ void RunL();
+
+ //
+ // CActive's DoCancel()
+ //
+ void DoCancel();
+
+ //
+ // Cancel operation and call callback.
+ //
+ void CancelOperation(pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_status);
+
+ //
+ // Accessors
+ //
+ void* get_user_data() const
+ {
+ return user_data_;
+ }
+ void set_user_data(void *user_data)
+ {
+ user_data_ = user_data;
+ }
+ pj_ioqueue_op_key_t *get_op_key() const
+ {
+ return pending_data_.common_.op_key_;
+ }
+ CPjSocket* get_pj_socket()
+ {
+ return sock_;
+ }
+
+private:
+ // Type of pending operation.
+ enum Type {
+ TYPE_NONE,
+ TYPE_READ,
+ TYPE_ACCEPT,
+ };
+
+ // Static data.
+ pj_ioqueue_t *ioqueue_;
+ pj_ioqueue_key_t *key_;
+ CPjSocket *sock_;
+ pj_ioqueue_callback cb_;
+ void *user_data_;
+
+ // Symbian data.
+ TPtr8 aBufferPtr_;
+ TInetAddr aAddress_;
+
+ // Application data.
+ Type type_;
+
+ union Pending_Data
+ {
+ struct Common
+ {
+ pj_ioqueue_op_key_t *op_key_;
+ } common_;
+
+ struct Pending_Read
+ {
+ pj_ioqueue_op_key_t *op_key_;
+ pj_sockaddr_t *addr_;
+ int *addrlen_;
+ } read_;
+
+ struct Pending_Accept
+ {
+ pj_ioqueue_op_key_t *op_key_;
+ pj_sock_t *new_sock_;
+ pj_sockaddr_t *local_;
+ pj_sockaddr_t *remote_;
+ int *addrlen_;
+ } accept_;
+ };
+
+ union Pending_Data pending_data_;
+ RSocket blank_sock_;
+
+ CIoqueueCallback(pj_ioqueue_t *ioqueue,
+ pj_ioqueue_key_t *key, pj_sock_t sock,
+ const pj_ioqueue_callback *cb, void *user_data)
+ : CActive(CActive::EPriorityStandard),
+ ioqueue_(ioqueue), key_(key), sock_((CPjSocket*)sock),
+ user_data_(user_data), aBufferPtr_(NULL, 0), type_(TYPE_NONE)
+ {
+ pj_memcpy(&cb_, cb, sizeof(*cb));
+ }
+
+
+ void ConstructL()
+ {
+ CActiveScheduler::Add(this);
+ }
+
+ void HandleReadCompletion();
+ CPjSocket *HandleAcceptCompletion();
+};
+
+
+CIoqueueCallback* CIoqueueCallback::NewL(pj_ioqueue_t *ioqueue,
+ pj_ioqueue_key_t *key,
+ pj_sock_t sock,
+ const pj_ioqueue_callback *cb,
+ void *user_data)
+{
+ CIoqueueCallback *self = new CIoqueueCallback(ioqueue, key, sock,
+ cb, user_data);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+
+ return self;
+}
+
+
+//
+// Start asynchronous recv() operation
+//
+pj_status_t CIoqueueCallback::StartRead(pj_ioqueue_op_key_t *op_key,
+ void *buf, pj_ssize_t *size,
+ unsigned flags,
+ pj_sockaddr_t *addr, int *addrlen)
+{
+ PJ_ASSERT_RETURN(IsActive()==false, PJ_EBUSY);
+ PJ_ASSERT_RETURN(pending_data_.common_.op_key_==NULL, PJ_EBUSY);
+
+ flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
+
+ pending_data_.read_.op_key_ = op_key;
+ pending_data_.read_.addr_ = addr;
+ pending_data_.read_.addrlen_ = addrlen;
+
+ aBufferPtr_.Set((TUint8*)buf, 0, (TInt)*size);
+
+ type_ = TYPE_READ;
+ if (addr && addrlen) {
+ sock_->Socket().RecvFrom(aBufferPtr_, aAddress_, flags, iStatus);
+ } else {
+ aAddress_.SetAddress(0);
+ aAddress_.SetPort(0);
+ sock_->Socket().Recv(aBufferPtr_, flags, iStatus);
+ }
+
+ if (iStatus==KRequestPending) {
+ SetActive();
+ return PJ_EPENDING;
+ } else {
+ // Complete immediately (with success or error)
+ if (iStatus == KErrNone) {
+ *size = aBufferPtr_.Length();
+ HandleReadCompletion();
+ return PJ_SUCCESS;
+ }
+ else {
+ pending_data_.read_.op_key_ = NULL;
+ pending_data_.read_.addr_ = NULL;
+ pending_data_.read_.addrlen_ = NULL;
+ return PJ_RETURN_OS_ERROR(iStatus.Int());
+ }
+ }
+}
+
+
+//
+// Start asynchronous accept() operation.
+//
+pj_status_t CIoqueueCallback::StartAccept(pj_ioqueue_op_key_t *op_key,
+ pj_sock_t *new_sock,
+ pj_sockaddr_t *local,
+ pj_sockaddr_t *remote,
+ int *addrlen )
+{
+ PJ_ASSERT_RETURN(IsActive()==false, PJ_EBUSY);
+ PJ_ASSERT_RETURN(pending_data_.common_.op_key_==NULL, PJ_EBUSY);
+
+ pending_data_.accept_.op_key_ = op_key;
+ pending_data_.accept_.new_sock_ = new_sock;
+ pending_data_.accept_.local_ = local;
+ pending_data_.accept_.remote_ = remote;
+ pending_data_.accept_.addrlen_ = addrlen;
+
+ // Create blank socket
+ blank_sock_.Open(PjSymbianOS::Instance()->SocketServ());
+
+ type_ = TYPE_ACCEPT;
+ sock_->Socket().Accept(blank_sock_, iStatus);
+
+ if (iStatus==KRequestPending) {
+ SetActive();
+ return PJ_EPENDING;
+ } else {
+ // Accept() completed immediately (with success or error).
+ if (iStatus == KErrNone) {
+ HandleAcceptCompletion();
+ return PJ_SUCCESS;
+ }
+ else {
+ pending_data_.accept_.op_key_ = NULL;
+ pending_data_.accept_.new_sock_ = NULL;
+ pending_data_.accept_.local_ = NULL;
+ pending_data_.accept_.remote_ = NULL;
+ pending_data_.accept_.addrlen_ = NULL;
+ return PJ_RETURN_OS_ERROR(iStatus.Int());
+ }
+ }
+}
+
+
+//
+// Handle asynchronous RecvFrom() completion
+//
+void CIoqueueCallback::HandleReadCompletion()
+{
+ if (pending_data_.read_.addr_) {
+ PjSymbianOS::Addr2pj(aAddress_,
+ *(pj_sockaddr_in*)pending_data_.read_.addr_);
+ pending_data_.read_.addr_ = NULL;
+ }
+ if (pending_data_.read_.addrlen_) {
+ *pending_data_.read_.addrlen_ = sizeof(pj_sockaddr_in);
+ pending_data_.read_.addrlen_ = NULL;
+ }
+
+ pending_data_.read_.op_key_ = NULL;
+}
+
+
+//
+// Handle asynchronous Accept() completion.
+//
+CPjSocket *CIoqueueCallback::HandleAcceptCompletion()
+{
+ CPjSocket *pjNewSock = new CPjSocket(blank_sock_);
+
+ if (pending_data_.accept_.new_sock_) {
+ *pending_data_.accept_.new_sock_ = (pj_sock_t)pjNewSock;
+ pending_data_.accept_.new_sock_ = NULL;
+ }
+
+ if (pending_data_.accept_.local_) {
+ TInetAddr aAddr;
+ pj_sockaddr_in *ptr_sockaddr;
+
+ blank_sock_.LocalName(aAddr);
+ ptr_sockaddr = (pj_sockaddr_in*)pending_data_.accept_.local_;
+ PjSymbianOS::Addr2pj(aAddr, *ptr_sockaddr);
+ pending_data_.accept_.local_ = NULL;
+ }
+
+ if (pending_data_.accept_.remote_) {
+ TInetAddr aAddr;
+ pj_sockaddr_in *ptr_sockaddr;
+
+ blank_sock_.RemoteName(aAddr);
+ ptr_sockaddr = (pj_sockaddr_in*)pending_data_.accept_.remote_;
+ PjSymbianOS::Addr2pj(aAddr, *ptr_sockaddr);
+ pending_data_.accept_.remote_ = NULL;
+ }
+
+ if (pending_data_.accept_.addrlen_) {
+ *pending_data_.accept_.addrlen_ = sizeof(pj_sockaddr_in);
+ pending_data_.accept_.addrlen_ = NULL;
+ }
+
+ return pjNewSock;
+}
+
+
+//
+// Completion callback.
+//
+void CIoqueueCallback::RunL()
+{
+ Type cur_type = type_;
+
+ type_ = TYPE_NONE;
+
+ if (cur_type == TYPE_READ) {
+ //
+ // Completion of asynchronous RecvFrom()
+ //
+
+ /* Clear op_key (save it to temp variable first!) */
+ pj_ioqueue_op_key_t *op_key = pending_data_.read_.op_key_;
+ pending_data_.read_.op_key_ = NULL;
+
+ // Handle failure condition
+ if (iStatus != KErrNone) {
+ if (cb_.on_read_complete) {
+ cb_.on_read_complete( key_, op_key,
+ -PJ_RETURN_OS_ERROR(iStatus.Int()));
+ }
+ return;
+ }
+
+ HandleReadCompletion();
+
+ /* Call callback */
+ if (cb_.on_read_complete) {
+ cb_.on_read_complete(key_, op_key, aBufferPtr_.Length());
+ }
+
+ } else if (cur_type == TYPE_ACCEPT) {
+ //
+ // Completion of asynchronous Accept()
+ //
+
+ /* Clear op_key (save it to temp variable first!) */
+ pj_ioqueue_op_key_t *op_key = pending_data_.read_.op_key_;
+ pending_data_.read_.op_key_ = NULL;
+
+ // Handle failure condition
+ if (iStatus != KErrNone) {
+ if (pending_data_.accept_.new_sock_)
+ *pending_data_.accept_.new_sock_ = PJ_INVALID_SOCKET;
+
+ if (cb_.on_accept_complete) {
+ cb_.on_accept_complete( key_, op_key, PJ_INVALID_SOCKET,
+ -PJ_RETURN_OS_ERROR(iStatus.Int()));
+ }
+ return;
+ }
+
+ CPjSocket *pjNewSock = HandleAcceptCompletion();
+
+ // Call callback.
+ if (cb_.on_accept_complete) {
+ cb_.on_accept_complete( key_, op_key, (pj_sock_t)pjNewSock,
+ PJ_SUCCESS);
+ }
+ }
+
+ ioqueue_->eventCount++;
+}
+
+//
+// CActive's DoCancel()
+//
+void CIoqueueCallback::DoCancel()
+{
+ if (type_ == TYPE_READ)
+ sock_->Socket().CancelRecv();
+ else if (type_ == TYPE_ACCEPT)
+ sock_->Socket().CancelAccept();
+
+ type_ = TYPE_NONE;
+}
+
+//
+// Cancel operation and call callback.
+//
+void CIoqueueCallback::CancelOperation(pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_status)
+{
+ Type cur_type = type_;
+
+ Cancel();
+
+ if (cur_type == TYPE_READ) {
+ if (cb_.on_read_complete)
+ cb_.on_read_complete(key_, op_key, bytes_status);
+ } else if (cur_type == TYPE_ACCEPT)
+ ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+/*
+ * IO Queue key structure.
+ */
+struct pj_ioqueue_key_t
+{
+ CIoqueueCallback *cbObj;
+};
+
+
+/*
+ * Return the name of the ioqueue implementation.
+ */
+PJ_DEF(const char*) pj_ioqueue_name(void)
+{
+ return "ioqueue-symbian";
+}
+
+
+/*
+ * Create a new I/O Queue framework.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool,
+ pj_size_t max_fd,
+ pj_ioqueue_t **p_ioqueue)
+{
+ pj_ioqueue_t *ioq;
+
+ PJ_UNUSED_ARG(max_fd);
+
+ ioq = (pj_ioqueue_t*) pj_pool_zalloc(pool, sizeof(pj_ioqueue_t));
+ ioq->timeoutTimer = CPjTimeoutTimer::NewL();
+ *p_ioqueue = ioq;
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Destroy the I/O queue.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioq )
+{
+ delete ioq->timeoutTimer;
+ ioq->timeoutTimer = NULL;
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Set the lock object to be used by the I/O Queue.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_set_lock( pj_ioqueue_t *ioq,
+ pj_lock_t *lock,
+ pj_bool_t auto_delete )
+{
+ /* Don't really need lock for now */
+ PJ_UNUSED_ARG(ioq);
+
+ if (auto_delete) {
+ pj_lock_destroy(lock);
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Register a socket to the I/O queue framework.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool,
+ pj_ioqueue_t *ioq,
+ pj_sock_t sock,
+ void *user_data,
+ const pj_ioqueue_callback *cb,
+ pj_ioqueue_key_t **p_key )
+{
+ pj_ioqueue_key_t *key;
+
+ key = (pj_ioqueue_key_t*) pj_pool_zalloc(pool, sizeof(pj_ioqueue_key_t));
+ key->cbObj = CIoqueueCallback::NewL(ioq, key, sock, cb, user_data);
+
+ *p_key = key;
+ return PJ_SUCCESS;
+}
+
+/*
+ * Unregister from the I/O Queue framework.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key )
+{
+ if (key == NULL || key->cbObj == NULL)
+ return PJ_SUCCESS;
+
+ // Cancel pending async object
+ if (key->cbObj && key->cbObj->IsActive()) {
+ key->cbObj->Cancel();
+ }
+
+ // Close socket.
+ key->cbObj->get_pj_socket()->Socket().Close();
+ delete key->cbObj->get_pj_socket();
+
+ // Delete async object.
+ if (key->cbObj) {
+ delete key->cbObj;
+ key->cbObj = NULL;
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Get user data associated with an ioqueue key.
+ */
+PJ_DEF(void*) pj_ioqueue_get_user_data( pj_ioqueue_key_t *key )
+{
+ return key->cbObj->get_user_data();
+}
+
+
+/*
+ * Set or change the user data to be associated with the file descriptor or
+ * handle or socket descriptor.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_set_user_data( pj_ioqueue_key_t *key,
+ void *user_data,
+ void **old_data)
+{
+ if (old_data)
+ *old_data = key->cbObj->get_user_data();
+ key->cbObj->set_user_data(user_data);
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Initialize operation key.
+ */
+PJ_DEF(void) pj_ioqueue_op_key_init( pj_ioqueue_op_key_t *op_key,
+ pj_size_t size )
+{
+ pj_memset(op_key, 0, size);
+}
+
+
+/*
+ * Check if operation is pending on the specified operation key.
+ */
+PJ_DEF(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key )
+{
+ return key->cbObj->get_op_key()==op_key &&
+ key->cbObj->IsActive();
+}
+
+
+/*
+ * Post completion status to the specified operation key and call the
+ * appropriate callback.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_status )
+{
+ if (pj_ioqueue_is_pending(key, op_key)) {
+ key->cbObj->CancelOperation(op_key, bytes_status);
+ }
+ return PJ_SUCCESS;
+}
+
+
+#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
+/**
+ * Instruct I/O Queue to accept incoming connection on the specified
+ * listening socket.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_accept( pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_sock_t *new_sock,
+ pj_sockaddr_t *local,
+ pj_sockaddr_t *remote,
+ int *addrlen )
+{
+
+ return key->cbObj->StartAccept(op_key, new_sock, local, remote, addrlen);
+}
+
+
+/*
+ * Initiate non-blocking socket connect.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key,
+ const pj_sockaddr_t *addr,
+ int addrlen )
+{
+ PJ_ASSERT_RETURN(addrlen == sizeof(pj_sockaddr_in), PJ_EINVAL);
+
+ RSocket &rSock = key->cbObj->get_pj_socket()->Socket();
+ TInetAddr inetAddr;
+ PjSymbianOS::pj2Addr(*(const pj_sockaddr_in*)addr, inetAddr);
+ TRequestStatus reqStatus;
+
+ // We don't support async connect for now.
+ PJ_TODO(IOQUEUE_SUPPORT_ASYNC_CONNECT);
+
+ rSock.Connect(inetAddr, reqStatus);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus == KErrNone)
+ return PJ_SUCCESS;
+
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+}
+
+
+#endif /* PJ_HAS_TCP */
+
+/*
+ * Poll the I/O Queue for completed events.
+ */
+PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioq,
+ const pj_time_val *timeout)
+{
+ CPjTimeoutTimer *timer;
+
+ if (timeout) {
+ //if (!ioq->timeoutTimer->IsActive())
+ if (0)
+ timer = ioq->timeoutTimer;
+ else
+ timer = CPjTimeoutTimer::NewL();
+
+ timer->StartTimer(timeout->sec*1000 + timeout->msec);
+
+ } else {
+ timer = NULL;
+ }
+
+ ioq->eventCount = 0;
+
+ do {
+ PjSymbianOS::Instance()->WaitForActiveObjects();
+ } while (ioq->eventCount == 0 && (!timer || (timer && !timer->HasTimedOut())));
+
+ if (timer && !timer->HasTimedOut())
+ timer->Cancel();
+
+ if (timer && timer != ioq->timeoutTimer)
+ delete timer;
+
+ return ioq->eventCount;
+}
+
+
+/*
+ * Instruct the I/O Queue to read from the specified handle.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ void *buffer,
+ pj_ssize_t *length,
+ pj_uint32_t flags )
+{
+ // Clear flag
+ flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
+ return key->cbObj->StartRead(op_key, buffer, length, flags, NULL, NULL);
+}
+
+
+/*
+ * This function behaves similarly as #pj_ioqueue_recv(), except that it is
+ * normally called for socket, and the remote address will also be returned
+ * along with the data.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ void *buffer,
+ pj_ssize_t *length,
+ pj_uint32_t flags,
+ pj_sockaddr_t *addr,
+ int *addrlen)
+{
+ if (key->cbObj->IsActive())
+ return PJ_EBUSY;
+
+ // Clear flag
+ flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
+ return key->cbObj->StartRead(op_key, buffer, length, flags, addr, addrlen);
+}
+
+
+/*
+ * Instruct the I/O Queue to write to the handle.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ const void *data,
+ pj_ssize_t *length,
+ pj_uint32_t flags )
+{
+ TRequestStatus reqStatus;
+ TPtrC8 aBuffer((const TUint8*)data, (TInt)*length);
+ TSockXfrLength aLen;
+
+ PJ_UNUSED_ARG(op_key);
+
+ // Forcing pending operation is not supported.
+ PJ_ASSERT_RETURN((flags & PJ_IOQUEUE_ALWAYS_ASYNC)==0, PJ_EINVAL);
+
+ // Clear flag
+ flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
+
+ key->cbObj->get_pj_socket()->Socket().Send(aBuffer, flags, reqStatus, aLen);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus.Int() != KErrNone)
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+
+ //At least in UIQ Emulator, aLen.Length() reports incorrect length
+ //for UDP (some newlc.com users seem to have reported this too).
+ //*length = aLen.Length();
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Instruct the I/O Queue to write to the handle.
+ */
+PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ const void *data,
+ pj_ssize_t *length,
+ pj_uint32_t flags,
+ const pj_sockaddr_t *addr,
+ int addrlen)
+{
+ TRequestStatus reqStatus;
+ TPtrC8 aBuffer;
+ TInetAddr inetAddr;
+ TSockXfrLength aLen;
+
+ PJ_UNUSED_ARG(op_key);
+
+ // Forcing pending operation is not supported.
+ PJ_ASSERT_RETURN((flags & PJ_IOQUEUE_ALWAYS_ASYNC)==0, PJ_EINVAL);
+
+ // Must be pj_sockaddr_in for now.
+ PJ_ASSERT_RETURN(addrlen == sizeof(pj_sockaddr_in), PJ_EINVAL);
+
+ // Clear flag
+ flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
+
+ aBuffer.Set((const TUint8*)data, (TInt)*length);
+ PjSymbianOS::pj2Addr(*(const pj_sockaddr_in*)addr, inetAddr);
+ CPjSocket *pjSock = key->cbObj->get_pj_socket();
+
+ pjSock->Socket().SendTo(aBuffer, inetAddr, flags, reqStatus, aLen);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus.Int() != KErrNone)
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+
+ //At least in UIQ Emulator, aLen.Length() reports incorrect length
+ //for UDP (some newlc.com users seem to have reported this too).
+ //*length = aLen.Length();
+ return PJ_SUCCESS;
+}
+
diff --git a/pjlib/src/pj/lock.c b/pjlib/src/pj/lock.c
index 8c2c8b3f..9c0a7fa6 100644
--- a/pjlib/src/pj/lock.c
+++ b/pjlib/src/pj/lock.c
@@ -64,7 +64,7 @@ static pj_status_t create_mutex_lock( pj_pool_t *pool,
PJ_ASSERT_RETURN(pool && lock, PJ_EINVAL);
- p_lock = pj_pool_alloc(pool, sizeof(pj_lock_t));
+ p_lock = PJ_POOL_ALLOC_T(pool, pj_lock_t);
if (!p_lock)
return PJ_ENOMEM;
@@ -152,7 +152,7 @@ PJ_DEF(pj_status_t) pj_lock_create_semaphore( pj_pool_t *pool,
PJ_ASSERT_RETURN(pool && lock, PJ_EINVAL);
- p_lock = pj_pool_alloc(pool, sizeof(pj_lock_t));
+ p_lock = PJ_POOL_ALLOC_T(pool, pj_lock_t);
if (!p_lock)
return PJ_ENOMEM;
diff --git a/pjlib/src/pj/log_writer_symbian_console.cpp b/pjlib/src/pj/log_writer_symbian_console.cpp
new file mode 100644
index 00000000..03ad9ede
--- /dev/null
+++ b/pjlib/src/pj/log_writer_symbian_console.cpp
@@ -0,0 +1,43 @@
+/* $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>
+#include <pj/os.h>
+#include <pj/unicode.h>
+
+#include "os_symbian.h"
+#include <e32cons.h>
+
+PJ_DEF(void) pj_log_write(int level, const char *buffer, int len)
+{
+#if 0
+ wchar_t wbuffer[PJ_LOG_MAX_SIZE];
+ CConsoleBase *cons = PjSymbianOS::Instance->Console();
+
+ pj_ansi_to_unicode(buffer, len, wbuffer, PJ_ARRAY_SIZE(wbuffer));
+
+
+ TPtrC16 aPtr((TUint16*)wbuffer, len);
+ console->Write(aPtr);
+#else
+ PJ_UNUSED_ARG(level);
+ PJ_UNUSED_ARG(buffer);
+ PJ_UNUSED_ARG(len);
+#endif
+}
+
diff --git a/pjlib/src/pj/os_core_symbian.cpp b/pjlib/src/pj/os_core_symbian.cpp
new file mode 100644
index 00000000..7386fd63
--- /dev/null
+++ b/pjlib/src/pj/os_core_symbian.cpp
@@ -0,0 +1,816 @@
+/* $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/os.h>
+#include <pj/assert.h>
+#include <pj/pool.h>
+#include <pj/log.h>
+#include <pj/rand.h>
+#include <pj/string.h>
+#include <pj/guid.h>
+#include <pj/except.h>
+#include <pj/errno.h>
+
+#include "os_symbian.h"
+
+
+#define PJ_MAX_TLS 32
+#define DUMMY_MUTEX ((pj_mutex_t*)101)
+#define DUMMY_SEMAPHORE ((pj_sem_t*)102)
+#define THIS_FILE "os_core_symbian.c"
+
+/*
+ * Note:
+ *
+ * The Symbian implementation does not support threading!
+ */
+
+struct pj_thread_t
+{
+ char obj_name[PJ_MAX_OBJ_NAME];
+ void *tls_values[PJ_MAX_TLS];
+
+#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
+ pj_uint32_t stk_size;
+ pj_uint32_t stk_max_usage;
+ char *stk_start;
+ const char *caller_file;
+ int caller_line;
+#endif
+
+} main_thread;
+
+struct pj_atomic_t
+{
+ pj_atomic_value_t value;
+};
+
+struct pj_sem_t
+{
+ int value;
+ int max;
+};
+
+/* Flags to indicate which TLS variables have been used */
+static int tls_vars[PJ_MAX_TLS];
+
+/* atexit handlers */
+static unsigned atexit_count;
+static void (*atexit_func[32])(void);
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// CPjTimeoutTimer implementation
+//
+
+CPjTimeoutTimer::CPjTimeoutTimer()
+: CActive(EPriorityNormal), hasTimedOut_(PJ_FALSE)
+{
+}
+
+CPjTimeoutTimer::~CPjTimeoutTimer()
+{
+ if (IsActive())
+ Cancel();
+ timer_.Close();
+}
+
+void CPjTimeoutTimer::ConstructL()
+{
+ hasTimedOut_ = PJ_FALSE;
+ timer_.CreateLocal();
+ CActiveScheduler::Add(this);
+}
+
+CPjTimeoutTimer *CPjTimeoutTimer::NewL()
+{
+ CPjTimeoutTimer *self = new CPjTimeoutTimer;
+ CleanupStack::PushL(self);
+
+ self->ConstructL();
+
+ CleanupStack::Pop(self);
+ return self;
+
+}
+
+void CPjTimeoutTimer::StartTimer(TUint miliSeconds)
+{
+ if (IsActive())
+ Cancel();
+
+ hasTimedOut_ = PJ_FALSE;
+ timer_.After(iStatus, miliSeconds * 1000);
+ SetActive();
+
+ pj_assert(iStatus==KRequestPending);
+}
+
+bool CPjTimeoutTimer::HasTimedOut() const
+{
+ return hasTimedOut_ != 0;
+}
+
+void CPjTimeoutTimer::RunL()
+{
+ hasTimedOut_ = PJ_TRUE;
+}
+
+void CPjTimeoutTimer::DoCancel()
+{
+ timer_.Cancel();
+}
+
+TInt CPjTimeoutTimer::RunError(TInt aError)
+{
+ PJ_UNUSED_ARG(aError);
+ return KErrNone;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// PjSymbianOS implementation
+//
+
+PjSymbianOS::PjSymbianOS()
+: isSocketServInitialized_(false), isResolverInitialized_(false),
+ console_(NULL), selectTimeoutTimer_(NULL)
+{
+}
+
+// Get PjSymbianOS instance
+PjSymbianOS *PjSymbianOS::Instance()
+{
+ static PjSymbianOS instance_;
+ return &instance_;
+}
+
+
+// Initialize
+TInt PjSymbianOS::Initialize()
+{
+ TInt err;
+
+ selectTimeoutTimer_ = CPjTimeoutTimer::NewL();
+
+#if 0
+ pj_assert(console_ == NULL);
+ TRAPD(err, console_ = Console::NewL(_L("PJLIB"),
+ TSize(KConsFullScreen,KConsFullScreen)));
+ return err;
+#endif
+
+ if (!isSocketServInitialized_) {
+ err = socketServ_.Connect();
+ if (err != KErrNone)
+ goto on_error;
+
+ isSocketServInitialized_ = true;
+ }
+
+ if (!isResolverInitialized_) {
+ err = hostResolver_.Open(SocketServ(), KAfInet, KSockStream);
+ if (err != KErrNone)
+ goto on_error;
+
+ isResolverInitialized_ = true;
+ }
+
+ return KErrNone;
+
+on_error:
+ Shutdown();
+ return err;
+}
+
+// Shutdown
+void PjSymbianOS::Shutdown()
+{
+ if (isResolverInitialized_) {
+ hostResolver_.Close();
+ isResolverInitialized_ = false;
+ }
+
+ if (isSocketServInitialized_) {
+ socketServ_.Close();
+ isSocketServInitialized_ = false;
+ }
+
+ if (console_) {
+ delete console_;
+ console_ = NULL;
+ }
+
+ if (selectTimeoutTimer_) {
+ delete selectTimeoutTimer_;
+ selectTimeoutTimer_ = NULL;
+ }
+}
+
+// Convert to Unicode
+TInt PjSymbianOS::ConvertToUnicode(TDes16 &aUnicode, const TDesC8 &aForeign)
+{
+#if 0
+ pj_assert(conv_ != NULL);
+ return conv_->ConvertToUnicode(aUnicode, aForeign, convToUnicodeState_);
+#else
+ return CnvUtfConverter::ConvertToUnicodeFromUtf8(aUnicode, aForeign);
+#endif
+}
+
+// Convert from Unicode
+TInt PjSymbianOS::ConvertFromUnicode(TDes8 &aForeign, const TDesC16 &aUnicode)
+{
+#if 0
+ pj_assert(conv_ != NULL);
+ return conv_->ConvertFromUnicode(aForeign, aUnicode, convToAnsiState_);
+#else
+ return CnvUtfConverter::ConvertFromUnicodeToUtf8(aForeign, aUnicode);
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// PJLIB os.h implementation
+//
+
+PJ_DEF(pj_uint32_t) pj_getpid(void)
+{
+ return 0;
+}
+
+
+PJ_DECL(void) pj_shutdown(void);
+
+/*
+ * pj_init(void).
+ * Init PJLIB!
+ */
+PJ_DEF(pj_status_t) pj_init(void)
+{
+ pj_ansi_strcpy(main_thread.obj_name, "pjthread");
+
+ // Init main thread
+ pj_memset(&main_thread, 0, sizeof(main_thread));
+
+ // Initialize PjSymbianOS instance
+ PjSymbianOS *os = PjSymbianOS::Instance();
+
+ PJ_LOG(4,(THIS_FILE, "Initializing PJLIB for Symbian OS.."));
+
+ TInt err;
+ err = os->Initialize();
+ if (err != KErrNone)
+ goto on_error;
+
+ PJ_LOG(5,(THIS_FILE, "PJLIB initialized."));
+ return PJ_SUCCESS;
+
+on_error:
+ pj_shutdown();
+ return PJ_RETURN_OS_ERROR(err);
+}
+
+
+PJ_DEF(pj_status_t) pj_atexit(void (*func)(void))
+{
+ if (atexit_count >= PJ_ARRAY_SIZE(atexit_func))
+ return PJ_ETOOMANY;
+
+ atexit_func[atexit_count++] = func;
+ return PJ_SUCCESS;
+}
+
+
+
+PJ_DEF(void) pj_shutdown(void)
+{
+ unsigned i;
+
+ /* Call atexit() functions */
+ for (i=atexit_count-1; i>=0; --i) {
+ (*atexit_func[i])();
+ }
+ atexit_count = 0;
+
+ /* Free exception ID */
+ if (PJ_NO_MEMORY_EXCEPTION != -1) {
+ pj_exception_id_free(PJ_NO_MEMORY_EXCEPTION);
+ PJ_NO_MEMORY_EXCEPTION = -1;
+ }
+
+ /* Clear static variables */
+ pj_errno_clear_handlers();
+
+ PjSymbianOS *os = PjSymbianOS::Instance();
+ os->Shutdown();
+}
+
+
+/*
+ * pj_thread_register(..)
+ */
+PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name,
+ pj_thread_desc desc,
+ pj_thread_t **thread_ptr)
+{
+ PJ_UNUSED_ARG(cstr_thread_name);
+ PJ_UNUSED_ARG(desc);
+ PJ_UNUSED_ARG(thread_ptr);
+ return PJ_EINVALIDOP;
+}
+
+
+/*
+ * pj_thread_create(...)
+ */
+PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool,
+ const char *thread_name,
+ pj_thread_proc *proc,
+ void *arg,
+ pj_size_t stack_size,
+ unsigned flags,
+ pj_thread_t **ptr_thread)
+{
+ PJ_UNUSED_ARG(pool);
+ PJ_UNUSED_ARG(thread_name);
+ PJ_UNUSED_ARG(proc);
+ PJ_UNUSED_ARG(arg);
+ PJ_UNUSED_ARG(stack_size);
+ PJ_UNUSED_ARG(flags);
+ PJ_UNUSED_ARG(ptr_thread);
+
+ /* Sorry mate, we don't support threading */
+ return PJ_ENOTSUP;
+}
+
+/*
+ * pj_thread-get_name()
+ */
+PJ_DEF(const char*) pj_thread_get_name(pj_thread_t *p)
+{
+ pj_assert(p == &main_thread);
+ return p->obj_name;
+}
+
+/*
+ * pj_thread_resume()
+ */
+PJ_DEF(pj_status_t) pj_thread_resume(pj_thread_t *p)
+{
+ PJ_UNUSED_ARG(p);
+ return PJ_EINVALIDOP;
+}
+
+/*
+ * pj_thread_this()
+ */
+PJ_DEF(pj_thread_t*) pj_thread_this(void)
+{
+ return &main_thread;
+}
+
+/*
+ * pj_thread_join()
+ */
+PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *rec)
+{
+ PJ_UNUSED_ARG(rec);
+ return PJ_EINVALIDOP;
+}
+
+/*
+ * pj_thread_destroy()
+ */
+PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *rec)
+{
+ PJ_UNUSED_ARG(rec);
+ return PJ_EINVALIDOP;
+}
+
+/*
+ * pj_thread_sleep()
+ */
+PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec)
+{
+ //Not a good idea, as we don't want network events to
+ //arrive while we're not polling them:
+ //PjSymbianOS::Instance()->WaitForActiveObjects();
+
+ //.. so rather use this, which won't wake up Active Objects:
+ User::After(msec*1000);
+
+ return PJ_SUCCESS;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+/*
+ * pj_thread_local_alloc()
+ */
+
+PJ_DEF(pj_status_t) pj_thread_local_alloc(long *index)
+{
+ unsigned i;
+
+ /* Find unused TLS variable */
+ for (i=0; i<PJ_ARRAY_SIZE(tls_vars); ++i) {
+ if (tls_vars[i] == 0)
+ break;
+ }
+
+ if (i == PJ_ARRAY_SIZE(tls_vars))
+ return PJ_ETOOMANY;
+
+ tls_vars[i] = 1;
+ *index = i;
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_thread_local_free()
+ */
+PJ_DEF(void) pj_thread_local_free(long index)
+{
+ PJ_ASSERT_ON_FAIL(index >= 0 && index < PJ_ARRAY_SIZE(tls_vars) &&
+ tls_vars[index] != 0, return);
+
+ tls_vars[index] = 0;
+}
+
+
+/*
+ * pj_thread_local_set()
+ */
+PJ_DEF(pj_status_t) pj_thread_local_set(long index, void *value)
+{
+ pj_thread_t *rec = pj_thread_this();
+
+ PJ_ASSERT_RETURN(index >= 0 && index < PJ_ARRAY_SIZE(tls_vars) &&
+ tls_vars[index] != 0, PJ_EINVAL);
+
+ rec->tls_values[index] = value;
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_thread_local_get()
+ */
+PJ_DEF(void*) pj_thread_local_get(long index)
+{
+ pj_thread_t *rec = pj_thread_this();
+
+ PJ_ASSERT_RETURN(index >= 0 && index < PJ_ARRAY_SIZE(tls_vars) &&
+ tls_vars[index] != 0, NULL);
+
+ return rec->tls_values[index];
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+/*
+ * Create atomic variable.
+ */
+PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool,
+ pj_atomic_value_t initial,
+ pj_atomic_t **atomic )
+{
+ *atomic = (pj_atomic_t*)pj_pool_alloc(pool, sizeof(struct pj_atomic_t));
+ (*atomic)->value = initial;
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Destroy atomic variable.
+ */
+PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var )
+{
+ PJ_UNUSED_ARG(atomic_var);
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Set the value of an atomic type, and return the previous value.
+ */
+PJ_DEF(void) pj_atomic_set( pj_atomic_t *atomic_var,
+ pj_atomic_value_t value)
+{
+ atomic_var->value = value;
+}
+
+
+/*
+ * Get the value of an atomic type.
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var)
+{
+ return atomic_var->value;
+}
+
+
+/*
+ * Increment the value of an atomic type.
+ */
+PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
+{
+ ++atomic_var->value;
+}
+
+
+/*
+ * Increment the value of an atomic type and get the result.
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var)
+{
+ return ++atomic_var->value;
+}
+
+
+/*
+ * Decrement the value of an atomic type.
+ */
+PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
+{
+ --atomic_var->value;
+}
+
+
+/*
+ * Decrement the value of an atomic type and get the result.
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var)
+{
+ return --atomic_var->value;
+}
+
+
+/*
+ * Add a value to an atomic type.
+ */
+PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var,
+ pj_atomic_value_t value)
+{
+ atomic_var->value += value;
+}
+
+
+/*
+ * Add a value to an atomic type and get the result.
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,
+ pj_atomic_value_t value)
+{
+ atomic_var->value += value;
+ return atomic_var->value;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+PJ_DEF(pj_status_t) pj_mutex_create( pj_pool_t *pool,
+ const char *name,
+ int type,
+ pj_mutex_t **mutex)
+{
+ PJ_UNUSED_ARG(pool);
+ PJ_UNUSED_ARG(name);
+ PJ_UNUSED_ARG(type);
+
+ *mutex = DUMMY_MUTEX;
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_mutex_create_simple()
+ */
+PJ_DEF(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool,
+ const char *name,
+ pj_mutex_t **mutex )
+{
+ return pj_mutex_create(pool, name, PJ_MUTEX_SIMPLE, mutex);
+}
+
+
+PJ_DEF(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
+ const char *name,
+ pj_mutex_t **mutex )
+{
+ return pj_mutex_create(pool, name, PJ_MUTEX_RECURSE, mutex);
+}
+
+
+/*
+ * pj_mutex_lock()
+ */
+PJ_DEF(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex)
+{
+ pj_assert(mutex == DUMMY_MUTEX);
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_mutex_trylock()
+ */
+PJ_DEF(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex)
+{
+ pj_assert(mutex == DUMMY_MUTEX);
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_mutex_unlock()
+ */
+PJ_DEF(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex)
+{
+ pj_assert(mutex == DUMMY_MUTEX);
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_mutex_destroy()
+ */
+PJ_DEF(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex)
+{
+ pj_assert(mutex == DUMMY_MUTEX);
+ return PJ_SUCCESS;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+/*
+ * RW Mutex
+ */
+#include "os_rwmutex.c"
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Enter critical section.
+ */
+PJ_DEF(void) pj_enter_critical_section(void)
+{
+ /* Nothing to do */
+}
+
+
+/*
+ * Leave critical section.
+ */
+PJ_DEF(void) pj_leave_critical_section(void)
+{
+ /* Nothing to do */
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Create semaphore.
+ */
+PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool,
+ const char *name,
+ unsigned initial,
+ unsigned max,
+ pj_sem_t **p_sem)
+{
+ pj_sem_t *sem;
+
+ PJ_UNUSED_ARG(name);
+
+ sem = (pj_sem_t*) pj_pool_zalloc(pool, sizeof(pj_sem_t));
+ sem->value = initial;
+ sem->max = max;
+
+ *p_sem = sem;
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Wait for semaphore.
+ */
+PJ_DEF(pj_status_t) pj_sem_wait(pj_sem_t *sem)
+{
+ if (sem->value > 0) {
+ sem->value--;
+ return PJ_SUCCESS;
+ } else {
+ pj_assert(!"Unexpected!");
+ return PJ_EINVALIDOP;
+ }
+}
+
+
+/*
+ * Try wait for semaphore.
+ */
+PJ_DEF(pj_status_t) pj_sem_trywait(pj_sem_t *sem)
+{
+ if (sem->value > 0) {
+ sem->value--;
+ return PJ_SUCCESS;
+ } else {
+ pj_assert(!"Unexpected!");
+ return PJ_EINVALIDOP;
+ }
+}
+
+
+/*
+ * Release semaphore.
+ */
+PJ_DEF(pj_status_t) pj_sem_post(pj_sem_t *sem)
+{
+ sem->value++;
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Destroy semaphore.
+ */
+PJ_DEF(pj_status_t) pj_sem_destroy(pj_sem_t *sem)
+{
+ PJ_UNUSED_ARG(sem);
+ return PJ_SUCCESS;
+}
+
+
+#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK != 0
+/*
+ * The implementation of stack checking.
+ */
+PJ_DEF(void) pj_thread_check_stack(const char *file, int line)
+{
+ char stk_ptr;
+ pj_uint32_t usage;
+ pj_thread_t *thread = pj_thread_this();
+
+ pj_assert(thread);
+
+ /* Calculate current usage. */
+ usage = (&stk_ptr > thread->stk_start) ? &stk_ptr - thread->stk_start :
+ thread->stk_start - &stk_ptr;
+
+ /* Assert if stack usage is dangerously high. */
+ pj_assert("STACK OVERFLOW!! " && (usage <= thread->stk_size - 128));
+
+ /* Keep statistic. */
+ if (usage > thread->stk_max_usage) {
+ thread->stk_max_usage = usage;
+ thread->caller_file = file;
+ thread->caller_line = line;
+ }
+}
+
+/*
+ * Get maximum stack usage statistic.
+ */
+PJ_DEF(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread)
+{
+ return thread->stk_max_usage;
+}
+
+/*
+ * Dump thread stack status.
+ */
+PJ_DEF(pj_status_t) pj_thread_get_stack_info(pj_thread_t *thread,
+ const char **file,
+ int *line)
+{
+ pj_assert(thread);
+
+ *file = thread->caller_file;
+ *line = thread->caller_line;
+ return 0;
+}
+
+#endif /* PJ_OS_HAS_CHECK_STACK */
diff --git a/pjlib/src/pj/os_error_symbian.cpp b/pjlib/src/pj/os_error_symbian.cpp
new file mode 100644
index 00000000..dcacf288
--- /dev/null
+++ b/pjlib/src/pj/os_error_symbian.cpp
@@ -0,0 +1,171 @@
+/* $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/errno.h>
+#include <pj/assert.h>
+#include <pj/compat/stdarg.h>
+#include <pj/unicode.h>
+#include <pj/string.h>
+
+#include <e32err.h>
+#include <in_sock.h>
+
+
+#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING!=0)
+static const struct {
+ pj_os_err_type code;
+ const char *msg;
+} gaErrorList[] = {
+ /*
+ * Generic error -1 to -46
+ */
+ PJ_BUILD_ERR( KErrNotFound, "Unable to find the specified object"),
+ PJ_BUILD_ERR( KErrGeneral, "General (unspecified) error"),
+ PJ_BUILD_ERR( KErrCancel, "The operation was cancelled"),
+ PJ_BUILD_ERR( KErrNoMemory, "Not enough memory"),
+ PJ_BUILD_ERR( KErrNotSupported, "The operation requested is not supported"),
+ PJ_BUILD_ERR( KErrArgument, "Bad request"),
+ PJ_BUILD_ERR( KErrTotalLossOfPrecision, "Total loss of precision"),
+ PJ_BUILD_ERR( KErrBadHandle, "Bad object"),
+ PJ_BUILD_ERR( KErrOverflow, "Overflow"),
+ PJ_BUILD_ERR( KErrUnderflow, "Underflow"),
+ PJ_BUILD_ERR( KErrAlreadyExists,"Already exists"),
+ PJ_BUILD_ERR( KErrPathNotFound, "Unable to find the specified folder"),
+ PJ_BUILD_ERR( KErrDied, "Closed"),
+ PJ_BUILD_ERR( KErrInUse, "The specified object is currently in use by another program"),
+ PJ_BUILD_ERR( KErrServerTerminated, "Server has closed"),
+ PJ_BUILD_ERR( KErrServerBusy, "Server busy"),
+ PJ_BUILD_ERR( KErrCompletion, "Completion error"),
+ PJ_BUILD_ERR( KErrNotReady, "Not ready"),
+ PJ_BUILD_ERR( KErrUnknown, "Unknown error"),
+ PJ_BUILD_ERR( KErrCorrupt, "Corrupt"),
+ PJ_BUILD_ERR( KErrAccessDenied, "Access denied"),
+ PJ_BUILD_ERR( KErrLocked, "Locked"),
+ PJ_BUILD_ERR( KErrWrite, "Failed to write"),
+ PJ_BUILD_ERR( KErrDisMounted, "Wrong disk present"),
+ PJ_BUILD_ERR( KErrEof, "Unexpected end of file"),
+ PJ_BUILD_ERR( KErrDiskFull, "Disk full"),
+ PJ_BUILD_ERR( KErrBadDriver, "Bad device driver"),
+ PJ_BUILD_ERR( KErrBadName, "Bad name"),
+ PJ_BUILD_ERR( KErrCommsLineFail,"Comms line failed"),
+ PJ_BUILD_ERR( KErrCommsFrame, "Comms frame error"),
+ PJ_BUILD_ERR( KErrCommsOverrun, "Comms overrun error"),
+ PJ_BUILD_ERR( KErrCommsParity, "Comms parity error"),
+ PJ_BUILD_ERR( KErrTimedOut, "Timed out"),
+ PJ_BUILD_ERR( KErrCouldNotConnect, "Failed to connect"),
+ PJ_BUILD_ERR( KErrCouldNotDisconnect, "Failed to disconnect"),
+ PJ_BUILD_ERR( KErrDisconnected, "Disconnected"),
+ PJ_BUILD_ERR( KErrBadLibraryEntryPoint, "Bad library entry point"),
+ PJ_BUILD_ERR( KErrBadDescriptor,"Bad descriptor"),
+ PJ_BUILD_ERR( KErrAbort, "Interrupted"),
+ PJ_BUILD_ERR( KErrTooBig, "Too big"),
+ PJ_BUILD_ERR( KErrDivideByZero, "Divide by zero"),
+ PJ_BUILD_ERR( KErrBadPower, "Batteries too low"),
+ PJ_BUILD_ERR( KErrDirFull, "Folder full"),
+ PJ_BUILD_ERR( KErrHardwareNotAvailable, ""),
+ PJ_BUILD_ERR( KErrSessionClosed, ""),
+ PJ_BUILD_ERR( KErrPermissionDenied, ""),
+
+ /*
+ * Socket errors (-190 - -1000)
+ */
+ PJ_BUILD_ERR( KErrNetUnreach, "Could not connect to the network. Currently unreachable"),
+ PJ_BUILD_ERR( KErrHostUnreach, "Could not connect to the specified server"),
+ PJ_BUILD_ERR( KErrNoProtocolOpt,"The specified server refuses the selected protocol"),
+ PJ_BUILD_ERR( KErrUrgentData, ""),
+ PJ_BUILD_ERR( KErrWouldBlock, "Conflicts with KErrExtended, but cannot occur in practice"),
+
+ {0, NULL}
+};
+
+#endif /* PJ_HAS_ERROR_STRING */
+
+
+PJ_DEF(pj_status_t) pj_get_os_error(void)
+{
+ return -1;
+}
+
+PJ_DEF(void) pj_set_os_error(pj_status_t code)
+{
+ PJ_UNUSED_ARG(code);
+}
+
+PJ_DEF(pj_status_t) pj_get_netos_error(void)
+{
+ return -1;
+}
+
+PJ_DEF(void) pj_set_netos_error(pj_status_t code)
+{
+ PJ_UNUSED_ARG(code);
+}
+
+PJ_BEGIN_DECL
+
+ PJ_DECL(int) platform_strerror( pj_os_err_type os_errcode,
+ char *buf, pj_size_t bufsize);
+PJ_END_DECL
+
+/*
+ * platform_strerror()
+ *
+ * Platform specific error message. This file is called by pj_strerror()
+ * in errno.c
+ */
+PJ_DEF(int) platform_strerror( pj_os_err_type os_errcode,
+ char *buf, pj_size_t bufsize)
+{
+ int len = 0;
+
+ pj_assert(buf != NULL);
+ pj_assert(bufsize >= 0);
+
+ /*
+ * MUST NOT check stack here.
+ * This function might be called from PJ_CHECK_STACK() itself!
+ //PJ_CHECK_STACK();
+ */
+
+ if (!len) {
+#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING!=0)
+ int i;
+ for (i = 0; gaErrorList[i].msg; ++i) {
+ if (gaErrorList[i].code == os_errcode) {
+ len = strlen(gaErrorList[i].msg);
+ if ((pj_size_t)len >= bufsize) {
+ len = bufsize-1;
+ }
+ pj_memcpy(buf, gaErrorList[i].msg, len);
+ buf[len] = '\0';
+ break;
+ }
+ }
+#endif /* PJ_HAS_ERROR_STRING */
+
+ }
+
+ if (!len) {
+ len = pj_ansi_snprintf( buf, bufsize, "Symbian native error %d",
+ os_errcode);
+ buf[len] = '\0';
+ }
+
+ return len;
+}
+
diff --git a/pjlib/src/pj/os_rwmutex.c b/pjlib/src/pj/os_rwmutex.c
index 05728da6..27bc5adb 100644
--- a/pjlib/src/pj/os_rwmutex.c
+++ b/pjlib/src/pj/os_rwmutex.c
@@ -56,7 +56,7 @@ PJ_DEF(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name,
PJ_ASSERT_RETURN(pool && p_mutex, PJ_EINVAL);
*p_mutex = NULL;
- rwmutex = pj_pool_alloc(pool, sizeof(struct pj_rwmutex_t));
+ rwmutex = PJ_POOL_ALLOC_T(pool, pj_rwmutex_t);
status = pj_mutex_create_simple(pool, name, &rwmutex ->read_lock);
if (status != PJ_SUCCESS)
diff --git a/pjlib/src/pj/os_symbian.h b/pjlib/src/pj/os_symbian.h
new file mode 100644
index 00000000..06973104
--- /dev/null
+++ b/pjlib/src/pj/os_symbian.h
@@ -0,0 +1,302 @@
+/* $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 __OS_SYMBIAN_H__
+#define __OS_SYMBIAN_H__
+
+#include <pj/sock.h>
+
+#include <e32base.h>
+#include <e32cmn.h>
+#include <e32std.h>
+#include <ES_SOCK.H>
+#include <in_sock.h>
+#include <CHARCONV.H>
+#include <utf.h>
+#include <e32cons.h>
+
+// Forward declarations
+class CPjSocketReader;
+
+//
+// PJLIB Symbian's Socket
+//
+class CPjSocket
+{
+public:
+ enum
+ {
+ MAX_LEN = 1500,
+ };
+
+ // Construct CPjSocket
+ CPjSocket(RSocket &sock)
+ : sock_(sock), connected_(false), sockReader_(NULL)
+ {
+ }
+
+ // Destroy CPjSocket
+ ~CPjSocket();
+
+ // Get the internal RSocket
+ RSocket& Socket()
+ {
+ return sock_;
+ }
+
+ // Get socket connected flag.
+ bool IsConnected() const
+ {
+ return connected_;
+ }
+
+ // Set socket connected flag.
+ void SetConnected(bool connected)
+ {
+ connected_ = connected;
+ }
+
+ // Get socket reader, if any.
+ // May return NULL.
+ CPjSocketReader *Reader()
+ {
+ return sockReader_;
+ }
+
+ // Create socket reader.
+ CPjSocketReader *CreateReader(unsigned max_len=CPjSocket::MAX_LEN);
+
+private:
+ RSocket sock_; // Must not be reference, or otherwise
+ // it may point to local variable!
+ bool connected_;
+ CPjSocketReader *sockReader_;
+};
+
+
+//
+// Socket reader, used by select() and ioqueue abstraction
+//
+class CPjSocketReader : public CActive
+{
+public:
+ // Construct.
+ static CPjSocketReader *NewL(CPjSocket &sock, unsigned max_len=CPjSocket::MAX_LEN);
+
+ // Destroy;
+ ~CPjSocketReader();
+
+ // Start asynchronous read from the socket.
+ void StartRecv(void (*cb)(void *key)=NULL,
+ void *key=NULL,
+ TDes8 *aDesc = NULL,
+ TUint flags = 0);
+
+ // Start asynchronous read from the socket.
+ void StartRecvFrom(void (*cb)(void *key)=NULL,
+ void *key=NULL,
+ TDes8 *aDesc = NULL,
+ TUint flags = 0,
+ TSockAddr *fromAddr = NULL);
+
+ // Cancel asynchronous read.
+ void DoCancel();
+
+ // Implementation: called when read has completed.
+ void RunL();
+
+ // Check if there's pending data.
+ bool HasData() const
+ {
+ return buffer_.Length() != 0;
+ }
+
+ // Append data to aDesc, up to aDesc's maximum size.
+ // If socket is datagram based, buffer_ will be clared.
+ void ReadData(TDes8 &aDesc, TInetAddr *addr=NULL);
+
+private:
+ CPjSocket &sock_;
+ bool isDatagram_;
+ TPtr8 buffer_;
+ TInetAddr recvAddr_;
+
+ void (*readCb_)(void *key);
+ void *key_;
+
+ //
+ // Constructor
+ //
+ CPjSocketReader(CPjSocket &sock);
+ void ConstructL(unsigned max_len);
+};
+
+
+
+//
+// Time-out Timer Active Object
+//
+class CPjTimeoutTimer : public CActive
+{
+public:
+ static CPjTimeoutTimer *NewL();
+ ~CPjTimeoutTimer();
+
+ void StartTimer(TUint miliSeconds);
+ bool HasTimedOut() const;
+
+protected:
+ virtual void RunL();
+ virtual void DoCancel();
+ virtual TInt RunError(TInt aError);
+
+private:
+ RTimer timer_;
+ pj_bool_t hasTimedOut_;
+
+ CPjTimeoutTimer();
+ void ConstructL();
+};
+
+
+
+//
+// Symbian OS helper for PJLIB
+//
+class PjSymbianOS
+{
+public:
+ //
+ // Construct PjSymbianOS instance.
+ //
+ static PjSymbianOS *NewL();
+
+ //
+ // Get the singleton instance of PjSymbianOS
+ //
+ static PjSymbianOS *Instance();
+
+ //
+ // Initialize.
+ //
+ TInt Initialize();
+
+ //
+ // Shutdown.
+ //
+ void Shutdown();
+
+
+ //
+ // Socket helper.
+ //
+
+ // Get RSocketServ instance to be used by all sockets.
+ RSocketServ &SocketServ()
+ {
+ return socketServ_;
+ }
+
+ // Convert TInetAddr to pj_sockaddr_in
+ static inline void Addr2pj(const TInetAddr & sym_addr,
+ pj_sockaddr_in &pj_addr)
+ {
+ memset(&pj_addr, 0, sizeof(pj_sockaddr_in));
+ pj_addr.sin_family = PJ_AF_INET;
+ pj_addr.sin_addr.s_addr = sym_addr.Address();
+ pj_addr.sin_port = (pj_uint16_t) sym_addr.Port();
+ }
+
+
+ // Convert pj_sockaddr_in to TInetAddr
+ static inline void pj2Addr(const pj_sockaddr_in &pj_addr,
+ TInetAddr & sym_addr)
+ {
+ sym_addr.Init(KAfInet);
+ sym_addr.SetAddress((TUint32)pj_addr.sin_addr.s_addr);
+ sym_addr.SetPort(pj_addr.sin_port);
+ }
+
+
+ //
+ // Resolver helper
+ //
+
+ // Get RHostResolver instance
+ RHostResolver & GetResolver()
+ {
+ return hostResolver_;
+ }
+
+
+ //
+ // Unicode Converter
+ //
+
+ // Convert to Unicode
+ TInt ConvertToUnicode(TDes16 &aUnicode, const TDesC8 &aForeign);
+
+ // Convert from Unicode
+ TInt ConvertFromUnicode(TDes8 &aForeign, const TDesC16 &aUnicode);
+
+ //
+ // Get console
+ //
+
+ // Get console
+ CConsoleBase *Console()
+ {
+ return console_;
+ }
+
+ //
+ // Get select() timeout timer.
+ //
+ CPjTimeoutTimer *SelectTimeoutTimer()
+ {
+ return selectTimeoutTimer_;
+ }
+
+ //
+ // Wait for any active objects to run.
+ //
+ void WaitForActiveObjects(TInt aPriority = CActive::EPriorityStandard)
+ {
+ TInt aError;
+ User::WaitForAnyRequest();
+ CActiveScheduler::RunIfReady(aError, aPriority);
+ }
+
+private:
+ bool isSocketServInitialized_;
+ RSocketServ socketServ_;
+
+ bool isResolverInitialized_;
+ RHostResolver hostResolver_;
+
+ CConsoleBase* console_;
+
+ CPjTimeoutTimer *selectTimeoutTimer_;
+
+private:
+ PjSymbianOS();
+};
+
+
+#endif /* __OS_SYMBIAN_H__ */
+
diff --git a/pjlib/src/pj/pool.c b/pjlib/src/pj/pool.c
index 02b71ed5..9f47892d 100644
--- a/pjlib/src/pj/pool.c
+++ b/pjlib/src/pj/pool.c
@@ -170,7 +170,7 @@ PJ_DEF(pj_pool_t*) pj_pool_create_int( pj_pool_factory *f, const char *name,
{
pj_pool_t *pool;
pj_pool_block *block;
- unsigned char *buffer;
+ pj_uint8_t *buffer;
PJ_CHECK_STACK();
@@ -183,7 +183,7 @@ PJ_DEF(pj_pool_t*) pj_pool_create_int( pj_pool_factory *f, const char *name,
callback = f->policy.callback;
/* Allocate initial block */
- buffer = (*f->policy.block_alloc)(f, initial_size);
+ buffer = (pj_uint8_t*) (*f->policy.block_alloc)(f, initial_size);
if (!buffer)
return NULL;
diff --git a/pjlib/src/pj/pool_buf.c b/pjlib/src/pj/pool_buf.c
index f6f294b7..08885ea6 100644
--- a/pjlib/src/pj/pool_buf.c
+++ b/pjlib/src/pj/pool_buf.c
@@ -57,7 +57,7 @@ static void* stack_alloc(pj_pool_factory *factory, pj_size_t size)
PJ_UNUSED_ARG(factory);
- param = pj_thread_local_get(tls);
+ param = (struct creation_param*) pj_thread_local_get(tls);
if (param == NULL) {
/* Don't assert(), this is normal no-memory situation */
return NULL;
diff --git a/pjlib/src/pj/pool_caching.c b/pjlib/src/pj/pool_caching.c
index 35bc580b..b00bf108 100644
--- a/pjlib/src/pj/pool_caching.c
+++ b/pjlib/src/pj/pool_caching.c
@@ -85,7 +85,7 @@ PJ_DEF(void) pj_caching_pool_destroy( pj_caching_pool *cp )
/* Delete all pool in free list */
for (i=0; i < PJ_CACHING_POOL_ARRAY_SIZE; ++i) {
- pj_pool_t *pool = cp->free_list[i].next;
+ pj_pool_t *pool = (pj_pool_t*) cp->free_list[i].next;
pj_pool_t *next;
for (; pool != (void*)&cp->free_list[i]; pool = next) {
next = pool->next;
@@ -95,7 +95,7 @@ PJ_DEF(void) pj_caching_pool_destroy( pj_caching_pool *cp )
}
/* Delete all pools in used list */
- pool = cp->used_list.next;
+ pool = (pj_pool_t*) cp->used_list.next;
while (pool != (pj_pool_t*) &cp->used_list) {
pj_pool_t *next = pool->next;
pj_list_erase(pool);
@@ -164,7 +164,7 @@ static pj_pool_t* cpool_create_pool(pj_pool_factory *pf,
} else {
/* Get one pool from the list. */
- pool = cp->free_list[idx].next;
+ pool = (pj_pool_t*) cp->free_list[idx].next;
pj_list_erase(pool);
/* Initialize the pool. */
@@ -257,7 +257,7 @@ static void cpool_dump_status(pj_pool_factory *factory, pj_bool_t detail )
PJ_LOG(3,("cachpool", " Capacity=%u, max_capacity=%u, used_cnt=%u", \
cp->capacity, cp->max_capacity, cp->used_count));
if (detail) {
- pj_pool_t *pool = cp->used_list.next;
+ pj_pool_t *pool = (pj_pool_t*) cp->used_list.next;
pj_uint32_t total_used = 0, total_capacity = 0;
PJ_LOG(3,("cachpool", " Dumping all active pools:"));
while (pool != (void*)&cp->used_list) {
diff --git a/pjlib/src/pj/pool_policy_new.cpp b/pjlib/src/pj/pool_policy_new.cpp
new file mode 100644
index 00000000..367be0f3
--- /dev/null
+++ b/pjlib/src/pj/pool_policy_new.cpp
@@ -0,0 +1,73 @@
+/* $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/except.h>
+#include <pj/os.h>
+
+#if !PJ_HAS_POOL_ALT_API
+
+/*
+ * This file contains pool default policy definition and implementation.
+ */
+
+
+static void *operator_new(pj_pool_factory *factory, pj_size_t size)
+{
+ PJ_CHECK_STACK();
+ PJ_UNUSED_ARG(factory);
+ PJ_UNUSED_ARG(size);
+
+ return new char[size];
+}
+
+static void operator_delete(pj_pool_factory *factory, void *mem, pj_size_t size)
+{
+ PJ_CHECK_STACK();
+ PJ_UNUSED_ARG(factory);
+ PJ_UNUSED_ARG(size);
+
+ char *p = (char*)mem;
+ delete [] p;
+}
+
+static void default_pool_callback(pj_pool_t *pool, pj_size_t size)
+{
+ PJ_CHECK_STACK();
+ PJ_UNUSED_ARG(pool);
+ PJ_UNUSED_ARG(size);
+
+ PJ_THROW(PJ_NO_MEMORY_EXCEPTION);
+}
+
+pj_pool_factory_policy pj_pool_factory_default_policy =
+{
+ &operator_new,
+ &operator_delete,
+ &default_pool_callback,
+ 0
+};
+
+PJ_DEF(pj_pool_factory_policy*) pj_pool_factory_get_default_policy(void)
+{
+ return &pj_pool_factory_default_policy;
+}
+
+
+#endif /* PJ_HAS_POOL_ALT_API */
+
diff --git a/pjlib/src/pj/sock_select_symbian.cpp b/pjlib/src/pj/sock_select_symbian.cpp
new file mode 100644
index 00000000..cf45a62d
--- /dev/null
+++ b/pjlib/src/pj/sock_select_symbian.cpp
@@ -0,0 +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 <pj/sock_select.h>
+#include <pj/array.h>
+#include <pj/assert.h>
+#include <pj/os.h>
+#include "os_symbian.h"
+
+
+struct symbian_fd_set
+{
+ unsigned count;
+ CPjSocket *sock[FD_SETSIZE];
+};
+
+
+PJ_DEF(void) PJ_FD_ZERO(pj_fd_set_t *fdsetp)
+{
+ symbian_fd_set *fds = (symbian_fd_set *)fdsetp;
+ fds->count = 0;
+}
+
+
+PJ_DEF(void) PJ_FD_SET(pj_sock_t fd, pj_fd_set_t *fdsetp)
+{
+ symbian_fd_set *fds = (symbian_fd_set *)fdsetp;
+
+ PJ_ASSERT_ON_FAIL(fds->count < FD_SETSIZE, return);
+ fds->sock[fds->count++] = (CPjSocket*)fd;
+}
+
+
+PJ_DEF(void) PJ_FD_CLR(pj_sock_t fd, pj_fd_set_t *fdsetp)
+{
+ symbian_fd_set *fds = (symbian_fd_set *)fdsetp;
+ unsigned i;
+
+ for (i=0; i<fds->count; ++i) {
+ if (fds->sock[i] == (CPjSocket*)fd) {
+ pj_array_erase(fds->sock, sizeof(fds->sock[0]), fds->count, i);
+ --fds->count;
+ return;
+ }
+ }
+}
+
+
+PJ_DEF(pj_bool_t) PJ_FD_ISSET(pj_sock_t fd, const pj_fd_set_t *fdsetp)
+{
+ symbian_fd_set *fds = (symbian_fd_set *)fdsetp;
+ unsigned i;
+
+ for (i=0; i<fds->count; ++i) {
+ if (fds->sock[i] == (CPjSocket*)fd) {
+ return PJ_TRUE;
+ }
+ }
+
+ return PJ_FALSE;
+}
+
+PJ_DEF(pj_size_t) PJ_FD_COUNT(const pj_fd_set_t *fdsetp)
+{
+ symbian_fd_set *fds = (symbian_fd_set *)fdsetp;
+ return fds->count;
+}
+
+
+PJ_DEF(int) pj_sock_select( int n,
+ pj_fd_set_t *readfds,
+ pj_fd_set_t *writefds,
+ pj_fd_set_t *exceptfds,
+ const pj_time_val *timeout)
+{
+ CPjTimeoutTimer *pjTimer;
+ unsigned i;
+
+ PJ_UNUSED_ARG(n);
+ PJ_UNUSED_ARG(writefds);
+ PJ_UNUSED_ARG(exceptfds);
+
+ if (timeout) {
+ pjTimer = PjSymbianOS::Instance()->SelectTimeoutTimer();
+ pjTimer->StartTimer(timeout->sec*1000 + timeout->msec);
+
+ } else {
+ pjTimer = NULL;
+ }
+
+ /* Scan for readable sockets */
+
+ if (readfds) {
+ symbian_fd_set *fds = (symbian_fd_set *)readfds;
+
+ do {
+ /* Scan sockets for readily available data */
+ for (i=0; i<fds->count; ++i) {
+ CPjSocket *pjsock = fds->sock[i];
+
+ if (pjsock->Reader()) {
+ if (pjsock->Reader()->HasData() && !pjsock->Reader()->IsActive()) {
+
+ /* Found socket with data ready */
+ PJ_FD_ZERO(readfds);
+ PJ_FD_SET((pj_sock_t)pjsock, readfds);
+
+ /* Cancel timer, if any */
+ if (pjTimer) {
+ pjTimer->Cancel();
+ }
+
+ /* Clear writable and exception fd_set */
+ if (writefds)
+ PJ_FD_ZERO(writefds);
+ if (exceptfds)
+ PJ_FD_ZERO(exceptfds);
+
+ return 1;
+
+ } else if (!pjsock->Reader()->IsActive())
+ pjsock->Reader()->StartRecvFrom();
+
+ } else {
+ pjsock->CreateReader();
+ pjsock->Reader()->StartRecvFrom();
+ }
+ }
+
+ PjSymbianOS::Instance()->WaitForActiveObjects();
+
+ } while (pjTimer==NULL || !pjTimer->HasTimedOut());
+ }
+
+
+ /* Timeout */
+
+ if (readfds)
+ PJ_FD_ZERO(readfds);
+ if (writefds)
+ PJ_FD_ZERO(writefds);
+ if (exceptfds)
+ PJ_FD_ZERO(exceptfds);
+
+ return 0;
+}
+
diff --git a/pjlib/src/pj/sock_symbian.cpp b/pjlib/src/pj/sock_symbian.cpp
new file mode 100644
index 00000000..1b79098a
--- /dev/null
+++ b/pjlib/src/pj/sock_symbian.cpp
@@ -0,0 +1,931 @@
+/* $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/sock.h>
+#include <pj/addr_resolv.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/os.h>
+#include <pj/string.h>
+#include <pj/unicode.h>
+
+#include "os_symbian.h"
+
+
+/*
+ * Address families.
+ */
+const pj_uint16_t PJ_AF_UNIX = 0xFFFF;
+const pj_uint16_t PJ_AF_INET = KAfInet;
+const pj_uint16_t PJ_AF_INET6 = KAfInet6;
+const pj_uint16_t PJ_AF_PACKET = 0xFFFF;
+const pj_uint16_t PJ_AF_IRDA = 0xFFFF;
+
+/*
+ * Socket types conversion.
+ * The values here are indexed based on pj_sock_type
+ */
+const pj_uint16_t PJ_SOCK_STREAM= KSockStream;
+const pj_uint16_t PJ_SOCK_DGRAM = KSockDatagram;
+const pj_uint16_t PJ_SOCK_RAW = 0xFFFF;
+const pj_uint16_t PJ_SOCK_RDM = 0xFFFF;
+
+/* setsockop() is not really supported. */
+const pj_uint16_t PJ_SOL_SOCKET = 0xFFFF;
+const pj_uint16_t PJ_SOL_IP = 0xFFFF;
+const pj_uint16_t PJ_SOL_TCP = 0xFFFF;
+const pj_uint16_t PJ_SOL_UDP = 0xFFFF;
+const pj_uint16_t PJ_SOL_IPV6 = 0xFFFF;
+
+/* ioctl() is also not supported. */
+const pj_uint16_t PJ_SO_TYPE = 0xFFFF;
+const pj_uint16_t PJ_SO_RCVBUF = 0xFFFF;
+const pj_uint16_t PJ_SO_SNDBUF = 0xFFFF;
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// CPjSocket implementation.
+// (declaration is in os_symbian.h)
+//
+
+CPjSocket::~CPjSocket()
+{
+ if (sockReader_) {
+ if (sockReader_->IsActive())
+ sockReader_->Cancel();
+ delete sockReader_;
+ sockReader_ = NULL;
+ }
+ sock_.Close();
+}
+
+
+// Create socket reader.
+CPjSocketReader *CPjSocket::CreateReader(unsigned max_len)
+{
+ pj_assert(sockReader_ == NULL);
+ return sockReader_ = CPjSocketReader::NewL(*this, max_len);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// CPjSocketReader implementation
+// (declaration in os_symbian.h)
+//
+
+
+CPjSocketReader::CPjSocketReader(CPjSocket &sock)
+: CActive(EPriorityStandard),
+ sock_(sock), buffer_(NULL, 0), readCb_(NULL), key_(NULL)
+{
+}
+
+
+void CPjSocketReader::ConstructL(unsigned max_len)
+{
+ TProtocolDesc aProtocol;
+ TInt err;
+
+ err = sock_.Socket().Info(aProtocol);
+ User::LeaveIfError(err);
+
+ isDatagram_ = (aProtocol.iSockType == KSockDatagram);
+
+ TUint8 *ptr = new TUint8[max_len];
+ buffer_.Set(ptr, 0, (TInt)max_len);
+ CActiveScheduler::Add(this);
+}
+
+CPjSocketReader *CPjSocketReader::NewL(CPjSocket &sock, unsigned max_len)
+{
+ CPjSocketReader *self = new (ELeave) CPjSocketReader(sock);
+ CleanupStack::PushL(self);
+ self->ConstructL(max_len);
+ CleanupStack::Pop(self);
+
+ return self;
+}
+
+
+CPjSocketReader::~CPjSocketReader()
+{
+ const TUint8 *data = buffer_.Ptr();
+ delete [] data;
+}
+
+void CPjSocketReader::StartRecv(void (*cb)(void *key),
+ void *key,
+ TDes8 *aDesc,
+ TUint flags)
+{
+ StartRecvFrom(cb, key, aDesc, flags, NULL);
+}
+
+void CPjSocketReader::StartRecvFrom(void (*cb)(void *key),
+ void *key,
+ TDes8 *aDesc,
+ TUint flags,
+ TSockAddr *fromAddr)
+{
+ readCb_ = cb;
+ key_ = key;
+
+ if (aDesc == NULL) aDesc = &buffer_;
+ if (fromAddr == NULL) fromAddr = &recvAddr_;
+
+ sock_.Socket().RecvFrom(*aDesc, *fromAddr, flags, iStatus);
+ if (iStatus == KRequestPending)
+ SetActive();
+}
+
+void CPjSocketReader::DoCancel()
+{
+ sock_.Socket().CancelRecv();
+}
+
+void CPjSocketReader::RunL()
+{
+ void (*old_cb)(void *key) = readCb_;
+ void *old_key = key_;
+ bool is_active = IsActive();
+
+ readCb_ = NULL;
+ key_ = NULL;
+
+ if (old_cb) {
+ (*old_cb)(old_key);
+ }
+}
+
+// Append data to aDesc, up to aDesc's maximum size.
+// If socket is datagram based, buffer_ will be clared.
+void CPjSocketReader::ReadData(TDes8 &aDesc, TInetAddr *addr)
+{
+ if (isDatagram_)
+ aDesc.Zero();
+
+ if (buffer_.Length() == 0)
+ return;
+
+ TInt size_to_copy = aDesc.MaxLength() - aDesc.Length();
+ if (size_to_copy > buffer_.Length())
+ size_to_copy = buffer_.Length();
+
+ aDesc.Append(buffer_.Ptr(), size_to_copy);
+
+ if (isDatagram_)
+ buffer_.Zero();
+ else
+ buffer_.Delete(0, size_to_copy);
+
+ if (addr)
+ *addr = recvAddr_;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// PJLIB's sock.h implementation
+//
+
+/*
+ * Convert 16-bit value from network byte order to host byte order.
+ */
+PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
+{
+ /* There's no difference in host/network byte order in Symbian */
+ return netshort;
+}
+
+/*
+ * Convert 16-bit value from host byte order to network byte order.
+ */
+PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
+{
+ /* There's no difference in host/network byte order in Symbian */
+ return hostshort;
+}
+
+/*
+ * Convert 32-bit value from network byte order to host byte order.
+ */
+PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
+{
+ /* There's no difference in host/network byte order in Symbian */
+ return netlong;
+}
+
+/*
+ * Convert 32-bit value from host byte order to network byte order.
+ */
+PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
+{
+ /* There's no difference in host/network byte order in Symbian */
+ return hostlong;
+}
+
+/*
+ * Convert an Internet host address given in network byte order
+ * to string in standard numbers and dots notation.
+ */
+PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
+{
+ static TBuf<20> str16;
+ static char str8[20];
+
+ TInetAddr temp_addr((TUint32)inaddr.s_addr, (TUint)0);
+ temp_addr.Output(str16);
+
+ return pj_unicode_to_ansi(str16.PtrZ(), str16.Length(),
+ str8, sizeof(str8));
+}
+
+/*
+ * This function converts the Internet host address cp from the standard
+ * numbers-and-dots notation into binary data and stores it in the structure
+ * that inp points to.
+ */
+PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
+{
+ enum { MAXIPLEN = 16 };
+
+ /* Initialize output with PJ_INADDR_NONE.
+ * Some apps relies on this instead of the return value
+ * (and anyway the return value is quite confusing!)
+ */
+ inp->s_addr = PJ_INADDR_NONE;
+
+ /* Caution:
+ * this function might be called with cp->slen >= 16
+ * (i.e. when called with hostname to check if it's an IP addr).
+ */
+ PJ_ASSERT_RETURN(cp && cp->slen && inp, 0);
+ if (cp->slen >= 16) {
+ return 0;
+ }
+
+ char tempaddr8[MAXIPLEN];
+ pj_memcpy(tempaddr8, cp->ptr, cp->slen);
+ tempaddr8[cp->slen] = '\0';
+
+ wchar_t tempaddr16[MAXIPLEN];
+ pj_ansi_to_unicode(tempaddr8, pj_ansi_strlen(tempaddr8),
+ tempaddr16, sizeof(tempaddr16));
+
+ TBuf<MAXIPLEN> ip_addr(tempaddr16);
+
+ TInetAddr addr;
+ addr.Init(KAfInet);
+ if (addr.Input(ip_addr) == KErrNone) {
+ /* Success */
+ inp->s_addr = addr.Address();
+ return 1;
+ } else {
+ /* Error */
+ return 0;
+ }
+}
+
+/*
+ * Convert address string with numbers and dots to binary IP address.
+ */
+PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
+{
+ pj_in_addr addr;
+
+ pj_inet_aton(cp, &addr);
+ return addr;
+}
+
+/*
+ * Convert address string with numbers and dots to binary IP address.
+ */
+PJ_DEF(pj_in_addr) pj_inet_addr2(const char *cp)
+{
+ pj_str_t str = pj_str((char*)cp);
+ return pj_inet_addr(&str);
+}
+
+/*
+ * Set the IP address of an IP socket address from string address,
+ * with resolving the host if necessary. The string address may be in a
+ * standard numbers and dots notation or may be a hostname. If hostname
+ * is specified, then the function will resolve the host into the IP
+ * address.
+ */
+PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
+ const pj_str_t *str_addr)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(!str_addr || str_addr->slen < PJ_MAX_HOSTNAME,
+ (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
+
+ addr->sin_family = PJ_AF_INET;
+ pj_memset(addr->sin_zero, 0, sizeof(addr->sin_zero));
+
+ if (str_addr && str_addr->slen) {
+ addr->sin_addr = pj_inet_addr(str_addr);
+ if (addr->sin_addr.s_addr == PJ_INADDR_NONE) {
+ pj_hostent he;
+ pj_status_t rc;
+
+ rc = pj_gethostbyname(str_addr, &he);
+ if (rc == 0) {
+ addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
+ } else {
+ addr->sin_addr.s_addr = PJ_INADDR_NONE;
+ return rc;
+ }
+ }
+
+ } else {
+ addr->sin_addr.s_addr = 0;
+ }
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Set the IP address and port of an IP socket address.
+ * The string address may be in a standard numbers and dots notation or
+ * may be a hostname. If hostname is specified, then the function will
+ * resolve the host into the IP address.
+ */
+PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
+ const pj_str_t *str_addr,
+ pj_uint16_t port)
+{
+ PJ_ASSERT_RETURN(addr, (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
+
+ addr->sin_family = PJ_AF_INET;
+ pj_memset(addr->sin_zero, 0, sizeof(addr->sin_zero));
+ pj_sockaddr_in_set_port(addr, port);
+ return pj_sockaddr_in_set_str_addr(addr, str_addr);
+}
+
+
+/*
+ * Get hostname.
+ */
+PJ_DEF(const pj_str_t*) pj_gethostname(void)
+{
+ static char buf[PJ_MAX_HOSTNAME];
+ static pj_str_t hostname;
+
+ PJ_CHECK_STACK();
+
+ if (hostname.ptr == NULL) {
+ RHostResolver & resv = PjSymbianOS::Instance()->GetResolver();
+ TRequestStatus reqStatus;
+ THostName tmpName;
+
+ resv.GetHostName(tmpName, reqStatus);
+ User::WaitForRequest(reqStatus);
+
+ hostname.ptr = pj_unicode_to_ansi(tmpName.Ptr(), tmpName.Length(),
+ buf, sizeof(buf));
+ hostname.slen = tmpName.Length();
+ }
+ return &hostname;
+}
+
+/*
+ * Get first IP address associated with the hostname.
+ */
+PJ_DEF(pj_in_addr) pj_gethostaddr(void)
+{
+ pj_sockaddr_in addr;
+ const pj_str_t *hostname = pj_gethostname();
+
+ pj_sockaddr_in_set_str_addr(&addr, hostname);
+ return addr.sin_addr;
+}
+
+
+/*
+ * Create new socket/endpoint for communication and returns a descriptor.
+ */
+PJ_DEF(pj_status_t) pj_sock_socket(int af,
+ int type,
+ int proto,
+ pj_sock_t *p_sock)
+{
+ TInt rc;
+
+ PJ_CHECK_STACK();
+
+ /* Sanity checks. */
+ PJ_ASSERT_RETURN(p_sock!=NULL, PJ_EINVAL);
+
+ /* Set proto if none is specified. */
+ if (proto == 0) {
+ if (type == PJ_SOCK_STREAM)
+ proto = KProtocolInetTcp;
+ else if (type == PJ_SOCK_DGRAM)
+ proto = KProtocolInetUdp;
+ }
+
+ /* Create Symbian RSocket */
+ RSocket rSock;
+ rc = rSock.Open(PjSymbianOS::Instance()->SocketServ(), af, type, proto);
+ if (rc != KErrNone)
+ return PJ_RETURN_OS_ERROR(rc);
+
+
+ /* Wrap Symbian RSocket into PJLIB's CPjSocket, and return to caller */
+ CPjSocket *pjSock = new CPjSocket(rSock);
+ *p_sock = (pj_sock_t)pjSock;
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Bind socket.
+ */
+PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock,
+ const pj_sockaddr_t *addr,
+ int len)
+{
+ TInt rc;
+
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(sock != 0, PJ_EINVAL);
+ PJ_ASSERT_RETURN(addr && len == sizeof(pj_sockaddr_in), PJ_EINVAL);
+
+ // Convert PJLIB's pj_sockaddr_in into Symbian's TInetAddr
+ TInetAddr inetAddr;
+ PjSymbianOS::pj2Addr(*(pj_sockaddr_in*)addr, inetAddr);
+
+ // Get the RSocket instance
+ RSocket &rSock = ((CPjSocket*)sock)->Socket();
+
+ // Bind
+ rc = rSock.Bind(inetAddr);
+
+ return (rc==KErrNone) ? PJ_SUCCESS : PJ_RETURN_OS_ERROR(rc);
+}
+
+
+/*
+ * Bind socket.
+ */
+PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sock,
+ pj_uint32_t addr32,
+ pj_uint16_t port)
+{
+ pj_sockaddr_in addr;
+
+ PJ_CHECK_STACK();
+
+ pj_memset(&addr, 0, sizeof(addr));
+ addr.sin_family = PJ_AF_INET;
+ addr.sin_addr.s_addr = pj_htonl(addr32);
+ addr.sin_port = pj_htons(port);
+
+ return pj_sock_bind(sock, &addr, sizeof(pj_sockaddr_in));
+}
+
+
+/*
+ * Close socket.
+ */
+PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sock)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(sock != 0, PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+
+ // This will close the socket.
+ delete pjSock;
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Get remote's name.
+ */
+PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sock,
+ pj_sockaddr_t *addr,
+ int *namelen)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(sock && addr && namelen &&
+ *namelen>=sizeof(pj_sockaddr_in), PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+ RSocket &rSock = pjSock->Socket();
+
+ // Socket must be connected.
+ PJ_ASSERT_RETURN(pjSock->IsConnected(), PJ_EINVALIDOP);
+
+ TInetAddr inetAddr;
+ rSock.RemoteName(inetAddr);
+
+ PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr_in*)addr);
+ *namelen = sizeof(pj_sockaddr_in);
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Get socket name.
+ */
+PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sock,
+ pj_sockaddr_t *addr,
+ int *namelen)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(sock && addr && namelen &&
+ *namelen>=sizeof(pj_sockaddr_in), PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+ RSocket &rSock = pjSock->Socket();
+
+ TInetAddr inetAddr;
+ rSock.LocalName(inetAddr);
+
+ PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr_in*)addr);
+ *namelen = sizeof(pj_sockaddr_in);
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Send data
+ */
+PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock,
+ const void *buf,
+ pj_ssize_t *len,
+ unsigned flags)
+{
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+ RSocket &rSock = pjSock->Socket();
+
+ // send() should only be called to connected socket
+ PJ_ASSERT_RETURN(pjSock->IsConnected(), PJ_EINVALIDOP);
+
+ TPtrC8 data((const TUint8*)buf, (TInt)*len);
+ TRequestStatus reqStatus;
+ TSockXfrLength sentLen;
+
+ rSock.Send(data, flags, reqStatus, sentLen);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus.Int()==KErrNone) {
+ //*len = (TInt) sentLen.Length();
+ return PJ_SUCCESS;
+ } else
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+}
+
+
+/*
+ * Send data.
+ */
+PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock,
+ const void *buf,
+ pj_ssize_t *len,
+ unsigned flags,
+ const pj_sockaddr_t *to,
+ int tolen)
+{
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+ RSocket &rSock = pjSock->Socket();
+
+ // Only supports AF_INET for now
+ PJ_ASSERT_RETURN(tolen==sizeof(pj_sockaddr_in) &&
+ ((pj_sockaddr*)to)->addr.sa_family == PJ_AF_INET,
+ PJ_EINVAL);
+
+ TInetAddr inetAddr;
+ PjSymbianOS::pj2Addr(*(pj_sockaddr_in*)to, inetAddr);
+
+ TPtrC8 data((const TUint8*)buf, (TInt)*len);
+ TRequestStatus reqStatus;
+ TSockXfrLength sentLen;
+
+ rSock.SendTo(data, inetAddr, flags, reqStatus, sentLen);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus.Int()==KErrNone) {
+ //For some reason TSockXfrLength is not returning correctly!
+ //*len = (TInt) sentLen.Length();
+ return PJ_SUCCESS;
+ } else
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+}
+
+/*
+ * Receive data.
+ */
+PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock,
+ void *buf,
+ pj_ssize_t *len,
+ unsigned flags)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
+ PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+ RSocket &rSock = pjSock->Socket();
+
+ if (pjSock->Reader()) {
+ CPjSocketReader *reader = pjSock->Reader();
+
+ while (reader->IsActive() && !reader->HasData()) {
+ User::WaitForAnyRequest();
+ }
+
+ if (reader->HasData()) {
+ TPtr8 data((TUint8*)buf, (TInt)*len);
+ TInetAddr inetAddr;
+
+ reader->ReadData(data, &inetAddr);
+
+ *len = data.Length();
+ return PJ_SUCCESS;
+ }
+ }
+
+ TRequestStatus reqStatus;
+ TSockXfrLength recvLen;
+ TPtr8 data((TUint8*)buf, (TInt)*len, (TInt)*len);
+
+ rSock.Recv(data, flags, reqStatus, recvLen);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus == KErrNone) {
+ //*len = (TInt)recvLen.Length();
+ *len = data.Length();
+ return PJ_SUCCESS;
+ } else {
+ *len = -1;
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+ }
+}
+
+/*
+ * Receive data.
+ */
+PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
+ void *buf,
+ pj_ssize_t *len,
+ unsigned flags,
+ pj_sockaddr_t *from,
+ int *fromlen)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(sock && buf && len && from && fromlen, PJ_EINVAL);
+ PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL);
+ PJ_ASSERT_RETURN(*fromlen >= sizeof(pj_sockaddr_in), PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+ RSocket &rSock = pjSock->Socket();
+
+ if (pjSock->Reader()) {
+ CPjSocketReader *reader = pjSock->Reader();
+
+ while (reader->IsActive() && !reader->HasData()) {
+ User::WaitForAnyRequest();
+ }
+
+ if (reader->HasData()) {
+ TPtr8 data((TUint8*)buf, (TInt)*len);
+ TInetAddr inetAddr;
+
+ reader->ReadData(data, &inetAddr);
+
+ *len = data.Length();
+
+ if (from && fromlen) {
+ PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr_in*)from);
+ *fromlen = sizeof(pj_sockaddr_in);
+ }
+ return PJ_SUCCESS;
+ }
+ }
+
+ TInetAddr inetAddr;
+ TRequestStatus reqStatus;
+ TSockXfrLength recvLen;
+ TPtr8 data((TUint8*)buf, (TInt)*len, (TInt)*len);
+
+ rSock.RecvFrom(data, inetAddr, flags, reqStatus, recvLen);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus == KErrNone) {
+ //*len = (TInt)recvLen.Length();
+ *len = data.Length();
+ *fromlen = sizeof(pj_sockaddr_in);
+ PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr_in*)from);
+ return PJ_SUCCESS;
+ } else {
+ *len = -1;
+ *fromlen = -1;
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+ }
+}
+
+/*
+ * Get socket option.
+ */
+PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sock,
+ pj_uint16_t level,
+ pj_uint16_t optname,
+ void *optval,
+ int *optlen)
+{
+ // Not supported for now.
+ PJ_UNUSED_ARG(sock);
+ PJ_UNUSED_ARG(level);
+ PJ_UNUSED_ARG(optname);
+ PJ_UNUSED_ARG(optval);
+ PJ_UNUSED_ARG(optlen);
+ return PJ_EINVALIDOP;
+}
+
+/*
+ * Set socket option.
+ */
+PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock,
+ pj_uint16_t level,
+ pj_uint16_t optname,
+ const void *optval,
+ int optlen)
+{
+ // Not supported for now.
+ PJ_UNUSED_ARG(sock);
+ PJ_UNUSED_ARG(level);
+ PJ_UNUSED_ARG(optname);
+ PJ_UNUSED_ARG(optval);
+ PJ_UNUSED_ARG(optlen);
+ return PJ_EINVALIDOP;
+}
+
+/*
+ * Connect socket.
+ */
+PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock,
+ const pj_sockaddr_t *addr,
+ int namelen)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(sock && addr && namelen, PJ_EINVAL);
+ PJ_ASSERT_RETURN(((pj_sockaddr*)addr)->addr.sa_family == PJ_AF_INET,
+ PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+ RSocket &rSock = pjSock->Socket();
+
+ TInetAddr inetAddr;
+ TRequestStatus reqStatus;
+
+ PjSymbianOS::pj2Addr(*(pj_sockaddr_in*)addr, inetAddr);
+
+ rSock.Connect(inetAddr, reqStatus);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus == KErrNone) {
+ pjSock->SetConnected(true);
+ return PJ_SUCCESS;
+ } else {
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+ }
+}
+
+
+/*
+ * Shutdown socket.
+ */
+#if PJ_HAS_TCP
+PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sock,
+ int how)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(sock, PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+ RSocket &rSock = pjSock->Socket();
+
+ RSocket::TShutdown aHow;
+ if (how == PJ_SD_RECEIVE)
+ aHow = RSocket::EStopInput;
+ else if (how == PJ_SHUT_WR)
+ aHow = RSocket::EStopOutput;
+ else
+ aHow = RSocket::ENormal;
+
+ TRequestStatus reqStatus;
+
+ rSock.Shutdown(aHow, reqStatus);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus == KErrNone) {
+ return PJ_SUCCESS;
+ } else {
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+ }
+}
+
+/*
+ * Start listening to incoming connections.
+ */
+PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sock,
+ int backlog)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(sock && backlog, PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)sock;
+ RSocket &rSock = pjSock->Socket();
+
+ TInt rc = rSock.Listen((TUint)backlog);
+
+ if (rc == KErrNone) {
+ return PJ_SUCCESS;
+ } else {
+ return PJ_RETURN_OS_ERROR(rc);
+ }
+}
+
+/*
+ * Accept incoming connections
+ */
+PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t serverfd,
+ pj_sock_t *newsock,
+ pj_sockaddr_t *addr,
+ int *addrlen)
+{
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(serverfd && newsock, PJ_EINVAL);
+
+ CPjSocket *pjSock = (CPjSocket*)serverfd;
+ RSocket &rSock = pjSock->Socket();
+
+ // Create a 'blank' socket
+ RSocket newSock;
+ newSock.Open(PjSymbianOS::Instance()->SocketServ());
+
+ // Call Accept()
+ TRequestStatus reqStatus;
+
+ rSock.Accept(newSock, reqStatus);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus != KErrNone) {
+ return PJ_RETURN_OS_ERROR(reqStatus.Int());
+ }
+
+ // Create PJ socket
+ CPjSocket *newPjSock = new CPjSocket(newSock);
+ newPjSock->SetConnected(true);
+
+ *newsock = (pj_sock_t) newPjSock;
+
+ if (addr && addrlen) {
+ return pj_sock_getpeername(*newsock, addr, addrlen);
+ }
+
+ return PJ_SUCCESS;
+}
+#endif /* PJ_HAS_TCP */
+
+
diff --git a/pjlib/src/pj/timer.c b/pjlib/src/pj/timer.c
index e96a3e54..1e28b926 100644
--- a/pjlib/src/pj/timer.c
+++ b/pjlib/src/pj/timer.c
@@ -255,7 +255,8 @@ static void grow_heap(pj_timer_heap_t *ht)
pj_timer_entry **new_heap = 0;
- new_heap = pj_pool_alloc(ht->pool, sizeof(pj_timer_entry*) * new_size);
+ new_heap = (pj_timer_entry**)
+ pj_pool_alloc(ht->pool, sizeof(pj_timer_entry*) * new_size);
memcpy(new_heap, ht->heap, ht->max_size * sizeof(pj_timer_entry*));
//delete [] this->heap_;
ht->heap = new_heap;
@@ -263,7 +264,8 @@ static void grow_heap(pj_timer_heap_t *ht)
// Grow the array of timer ids.
new_timer_ids = 0;
- new_timer_ids = pj_pool_alloc(ht->pool, new_size * sizeof(pj_timer_id_t));
+ new_timer_ids = (pj_timer_id_t*)
+ pj_pool_alloc(ht->pool, new_size * sizeof(pj_timer_id_t));
memcpy( new_timer_ids, ht->timer_ids, ht->max_size * sizeof(pj_timer_id_t));
@@ -370,7 +372,7 @@ PJ_DEF(pj_status_t) pj_timer_heap_create( pj_pool_t *pool,
size += 2;
/* Allocate timer heap data structure from the pool */
- ht = pj_pool_alloc(pool, sizeof(pj_timer_heap_t));
+ ht = PJ_POOL_ALLOC_T(pool, pj_timer_heap_t);
if (!ht)
return PJ_ENOMEM;
@@ -386,12 +388,14 @@ PJ_DEF(pj_status_t) pj_timer_heap_create( pj_pool_t *pool,
ht->auto_delete_lock = 0;
// Create the heap array.
- ht->heap = pj_pool_alloc(pool, sizeof(pj_timer_entry*) * size);
+ ht->heap = (pj_timer_entry**)
+ pj_pool_alloc(pool, sizeof(pj_timer_entry*) * size);
if (!ht->heap)
return PJ_ENOMEM;
// Create the parallel
- ht->timer_ids = pj_pool_alloc( pool, sizeof(pj_timer_id_t) * size);
+ ht->timer_ids = (pj_timer_id_t *)
+ pj_pool_alloc( pool, sizeof(pj_timer_id_t) * size);
if (!ht->timer_ids)
return PJ_ENOMEM;
diff --git a/pjlib/src/pj/unicode_symbian.cpp b/pjlib/src/pj/unicode_symbian.cpp
new file mode 100644
index 00000000..62806fd1
--- /dev/null
+++ b/pjlib/src/pj/unicode_symbian.cpp
@@ -0,0 +1,69 @@
+/* $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/unicode.h>
+
+#include "os_symbian.h"
+
+
+/*
+ * Convert ANSI strings to Unicode strings.
+ */
+PJ_DEF(wchar_t*) pj_ansi_to_unicode( const char *str, pj_size_t len,
+ wchar_t *wbuf, pj_size_t wbuf_count)
+{
+ TPtrC8 aForeign((const TUint8*)str, (TInt)len);
+ TPtr16 aUnicode((TUint16*)wbuf, (TInt)(wbuf_count-1));
+ TInt left;
+
+ left = PjSymbianOS::Instance()->ConvertToUnicode(aUnicode, aForeign);
+
+ if (left != 0) {
+ // Error, or there are unconvertable characters
+ *wbuf = 0;
+ } else {
+ wbuf[len] = 0;
+ }
+
+ return wbuf;
+}
+
+
+/*
+ * Convert Unicode string to ANSI string.
+ */
+PJ_DEF(char*) pj_unicode_to_ansi( const wchar_t *wstr, pj_size_t len,
+ char *buf, pj_size_t buf_size)
+{
+ TPtrC16 aUnicode((const TUint16*)wstr, (TInt)len);
+ TPtr8 aForeign((TUint8*)buf, (TInt)(buf_size-1));
+ TInt left;
+
+ left = PjSymbianOS::Instance()->ConvertFromUnicode(aForeign, aUnicode);
+
+ if (left != 0) {
+ // Error, or there are unconvertable characters
+ buf[0] = '\0';
+ } else {
+ buf[len] = '\0';
+ }
+
+ return buf;
+}
+
+
diff --git a/pjlib/src/pjlib-test/ioq_perf.c b/pjlib/src/pjlib-test/ioq_perf.c
index adffc11c..cb8e8270 100644
--- a/pjlib/src/pjlib-test/ioq_perf.c
+++ b/pjlib/src/pjlib-test/ioq_perf.c
@@ -72,7 +72,7 @@ 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);
+ test_item *item = (test_item*)pj_ioqueue_get_user_data(key);
pj_status_t rc;
int data_is_available = 1;
@@ -150,7 +150,7 @@ 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);
+ test_item *item = (test_item*) pj_ioqueue_get_user_data(key);
//TRACE_((THIS_FILE, " write complete: sent = %d", bytes_sent));
@@ -188,7 +188,7 @@ struct thread_arg
/* The worker thread. */
static int worker_thread(void *p)
{
- struct thread_arg *arg = p;
+ struct thread_arg *arg = (struct thread_arg*) p;
const pj_time_val timeout = {0, 100};
int rc;
@@ -249,8 +249,9 @@ static int perform_test(int sock_type, const char *type_name,
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*));
+ items = (test_item*) pj_pool_alloc(pool, sockpair_cnt*sizeof(test_item));
+ thread = (pj_thread_t**)
+ pj_pool_alloc(pool, thread_cnt*sizeof(pj_thread_t*));
TRACE_((THIS_FILE, " creating ioqueue.."));
rc = pj_ioqueue_create(pool, sockpair_cnt*2, &ioqueue);
@@ -265,8 +266,8 @@ static int perform_test(int sock_type, const char *type_name,
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].outgoing_buffer = (char*) pj_pool_alloc(pool, buffer_size);
+ items[i].incoming_buffer = (char*) pj_pool_alloc(pool, buffer_size);
items[i].bytes_recv = items[i].bytes_sent = 0;
/* randomize outgoing buffer. */
@@ -331,7 +332,7 @@ static int perform_test(int sock_type, const char *type_name,
for (i=0; i<thread_cnt; ++i) {
struct thread_arg *arg;
- arg = pj_pool_zalloc(pool, sizeof(*arg));
+ arg = (thread_arg*) pj_pool_zalloc(pool, sizeof(*arg));
arg->id = i;
arg->ioqueue = ioqueue;
arg->counter = 0;
diff --git a/pjlib/src/pjlib-test/ioq_udp.c b/pjlib/src/pjlib-test/ioq_udp.c
index 4ccf30f9..e6f4c0f9 100644
--- a/pjlib/src/pjlib-test/ioq_udp.c
+++ b/pjlib/src/pjlib-test/ioq_udp.c
@@ -328,7 +328,7 @@ static void on_read_complete(pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_ssize_t bytes_read)
{
- unsigned *p_packet_cnt = pj_ioqueue_get_user_data(key);
+ unsigned *p_packet_cnt = (unsigned*) pj_ioqueue_get_user_data(key);
PJ_UNUSED_ARG(op_key);
PJ_UNUSED_ARG(bytes_read);
@@ -510,8 +510,9 @@ static int many_handles_test(void)
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));
+ key = (pj_ioqueue_key_t**)
+ pj_pool_alloc(pool, MAX*sizeof(pj_ioqueue_key_t*));
+ sock = (pj_sock_t*) pj_pool_alloc(pool, MAX*sizeof(pj_sock_t));
/* Create IOQueue */
rc = pj_ioqueue_create(pool, MAX, &ioqueue);
diff --git a/pjlib/src/pjlib-test/ioq_unreg.c b/pjlib/src/pjlib-test/ioq_unreg.c
index 1f7a98e7..ef50d048 100644
--- a/pjlib/src/pjlib-test/ioq_unreg.c
+++ b/pjlib/src/pjlib-test/ioq_unreg.c
@@ -123,7 +123,7 @@ static void on_read_complete(pj_ioqueue_key_t *key,
static int worker_thread(void *arg)
{
- pj_ioqueue_t *ioqueue = arg;
+ pj_ioqueue_t *ioqueue = (pj_ioqueue_t*) arg;
while (!thread_quitting) {
pj_time_val timeout = { 0, 20 };
@@ -210,9 +210,10 @@ static int perform_unreg_test(pj_ioqueue_t *ioqueue,
/* Initialize test data */
sock_data.pool = pj_pool_create(mem, "sd", 1000, 1000, NULL);
- sock_data.buffer = pj_pool_alloc(sock_data.pool, 128);
+ sock_data.buffer = (char*) pj_pool_alloc(sock_data.pool, 128);
sock_data.bufsize = 128;
- sock_data.op_key = pj_pool_alloc(sock_data.pool,
+ sock_data.op_key = (pj_ioqueue_op_key_t*)
+ pj_pool_alloc(sock_data.pool,
sizeof(*sock_data.op_key));
sock_data.received = 0;
sock_data.unregistered = 0;
diff --git a/pjlib/src/pjlib-test/main_symbian.cpp b/pjlib/src/pjlib-test/main_symbian.cpp
new file mode 100644
index 00000000..c2c808b8
--- /dev/null
+++ b/pjlib/src/pjlib-test/main_symbian.cpp
@@ -0,0 +1,193 @@
+//Auto-generated file. Please do not modify.
+//#include <e32cmn.h>
+
+//#pragma data_seg(".SYMBIAN")
+//__EMULATOR_IMAGE_HEADER2 (0x1000007a,0x00000000,0x00000000,EPriorityForeground,0x00000000u,0x00000000u,0x00000000,0x00000000,0x00000000,0)
+//#pragma data_seg()
+
+#include "test.h"
+#include <stdlib.h>
+#include <pj/errno.h>
+#include <pj/os.h>
+#include <pj/log.h>
+#include <pj/unicode.h>
+#include <stdio.h>
+
+#include <e32std.h>
+
+#if 0
+int main()
+{
+ int err = 0;
+ int exp = 0;
+
+ err = test_main();
+ //err = test_main();
+
+ if (err)
+ return err;
+ return exp;
+ //return 0;
+}
+
+#else
+#include <pj/os.h>
+
+#include <e32base.h>
+#include <e32std.h>
+#include <e32cons.h> // Console
+
+
+
+// Global Variables
+
+LOCAL_D CConsoleBase* console; // write all messages to this
+
+
+// Local Functions
+
+LOCAL_C void MainL()
+{
+ //
+ // add your program code here, example code below
+ //
+ int rc = test_main();
+
+ console->Printf(_L(" [press any key]\n"));
+ console->Getch();
+
+ CActiveScheduler::Stop();
+}
+
+class MyScheduler : public CActiveScheduler
+{
+public:
+ MyScheduler()
+ {}
+
+ void Error(TInt aError) const;
+};
+
+void MyScheduler::Error(TInt aError) const
+{
+ PJ_UNUSED_ARG(aError);
+}
+
+class ProgramStarter : public CActive
+{
+public:
+ static ProgramStarter *NewL();
+ void Start();
+
+protected:
+ ProgramStarter();
+ void ConstructL();
+ virtual void RunL();
+ virtual void DoCancel();
+ TInt RunError(TInt aError);
+
+private:
+ RTimer timer_;
+};
+
+ProgramStarter::ProgramStarter()
+: CActive(EPriorityNormal)
+{
+}
+
+void ProgramStarter::ConstructL()
+{
+ timer_.CreateLocal();
+ CActiveScheduler::Add(this);
+}
+
+ProgramStarter *ProgramStarter::NewL()
+{
+ ProgramStarter *self = new (ELeave) ProgramStarter;
+ CleanupStack::PushL(self);
+
+ self->ConstructL();
+
+ CleanupStack::Pop(self);
+ return self;
+}
+
+void ProgramStarter::Start()
+{
+ timer_.After(iStatus, 0);
+ SetActive();
+}
+
+void ProgramStarter::RunL()
+{
+ MainL();
+}
+
+void ProgramStarter::DoCancel()
+{
+}
+
+TInt ProgramStarter::RunError(TInt aError)
+{
+ PJ_UNUSED_ARG(aError);
+ return KErrNone;
+}
+
+
+LOCAL_C void DoStartL()
+ {
+ // Create active scheduler (to run active objects)
+ CActiveScheduler* scheduler = new (ELeave) MyScheduler;
+ CleanupStack::PushL(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+ ProgramStarter *starter = ProgramStarter::NewL();
+ starter->Start();
+
+ CActiveScheduler::Start();
+ }
+
+
+// Global Functions
+
+static void log_writer(int level, const char *buf, int len)
+{
+ wchar_t buf16[PJ_LOG_MAX_SIZE];
+
+ PJ_UNUSED_ARG(level);
+
+ pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
+
+ TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
+ console->Write(aBuf);
+}
+
+
+GLDEF_C TInt E32Main()
+ {
+ // Create cleanup stack
+ __UHEAP_MARK;
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+
+ // Create output console
+ TRAPD(createError, console = Console::NewL(_L("Console"), TSize(KConsFullScreen,KConsFullScreen)));
+ if (createError)
+ return createError;
+
+ pj_log_set_log_func(&log_writer);
+
+ // Run application code inside TRAP harness, wait keypress when terminated
+ TRAPD(mainError, DoStartL());
+ if (mainError)
+ console->Printf(_L(" failed, leave code = %d"), mainError);
+ console->Printf(_L(" [press any key]\n"));
+ console->Getch();
+
+ delete console;
+ delete cleanup;
+ __UHEAP_MARKEND;
+ return KErrNone;
+ }
+
+#endif /* if 0 */
+
diff --git a/pjlib/src/pjlib-test/sock.c b/pjlib/src/pjlib-test/sock.c
index a3df9b63..044b0f13 100644
--- a/pjlib/src/pjlib-test/sock.c
+++ b/pjlib/src/pjlib-test/sock.c
@@ -63,13 +63,8 @@
#define UDP_PORT 51234
#define TCP_PORT (UDP_PORT+10)
-#define BIG_DATA_LEN 9000
+#define BIG_DATA_LEN 8192
#define ADDRESS "127.0.0.1"
-#define A0 127
-#define A1 0
-#define A2 0
-#define A3 1
-
static char bigdata[BIG_DATA_LEN];
static char bigbuffer[BIG_DATA_LEN];
@@ -82,6 +77,12 @@ static int format_test(void)
char zero[64];
pj_sockaddr_in addr2;
const pj_str_t *hostname;
+#if defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
+ /* Symbian IP address is saved in host order */
+ unsigned char A[] = {1, 0, 0, 127};
+#else
+ unsigned char A[] = {127, 0, 0, 1};
+#endif
PJ_LOG(3,("test", "...format_test()"));
@@ -91,7 +92,7 @@ static int format_test(void)
/* Check the result. */
p = (unsigned char*)&addr;
- if (p[0]!=A0 || p[1]!=A1 || p[2]!=A2 || p[3]!=A3) {
+ if (p[0]!=A[0] || p[1]!=A[1] || p[2]!=A[2] || p[3]!=A[3]) {
PJ_LOG(3,("test", " error: mismatched address. p0=%d, p1=%d, "
"p2=%d, p3=%d", p[0] & 0xFF, p[1] & 0xFF,
p[2] & 0xFF, p[3] & 0xFF));
@@ -368,6 +369,8 @@ static int udp_test(void)
if (rc != 0)
goto on_error;
+// This test will fail on S60 3rd Edition MR2
+#if 0
/* connect() the sockets. */
rc = pj_sock_connect(cs, &dstaddr, sizeof(dstaddr));
if (rc != 0) {
@@ -385,6 +388,7 @@ static int udp_test(void)
sizeof(srcaddr));
if (rc != 0)
goto on_error;
+#endif
on_error:
retval = rc;
@@ -459,12 +463,70 @@ static int gethostbyname_test(void)
return 0;
}
+#if 0
+#include "../pj/os_symbian.h"
+static int connect_test()
+{
+ RSocketServ rSockServ;
+ RSocket rSock;
+ TInetAddr inetAddr;
+ TRequestStatus reqStatus;
+ char buffer[16];
+ TPtrC8 data((const TUint8*)buffer, (TInt)sizeof(buffer));
+ int rc;
+
+ rc = rSockServ.Connect();
+ if (rc != KErrNone)
+ return rc;
+
+ rc = rSock.Open(rSockServ, KAfInet, KSockDatagram, KProtocolInetUdp);
+ if (rc != KErrNone)
+ {
+ rSockServ.Close();
+ return rc;
+ }
+
+ inetAddr.Init(KAfInet);
+ inetAddr.Input(_L("127.0.0.1"));
+ inetAddr.SetPort(80);
+
+ rSock.Connect(inetAddr, reqStatus);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus != KErrNone) {
+ rSock.Close();
+ rSockServ.Close();
+ return rc;
+ }
+
+ rSock.Send(data, 0, reqStatus);
+ User::WaitForRequest(reqStatus);
+
+ if (reqStatus!=KErrNone) {
+ rSock.Close();
+ rSockServ.Close();
+ return rc;
+ }
+
+ rSock.Close();
+ rSockServ.Close();
+ return KErrNone;
+}
+#endif
+
int sock_test()
{
int rc;
pj_create_random_string(bigdata, BIG_DATA_LEN);
+// Enable this to demonstrate the error witn S60 3rd Edition MR2
+#if 0
+ rc = connect_test();
+ if (rc != 0)
+ return rc;
+#endif
+
rc = format_test();
if (rc != 0)
return rc;
diff --git a/pjlib/src/pjlib-test/sock_perf.c b/pjlib/src/pjlib-test/sock_perf.c
index efb8f065..1fa12082 100644
--- a/pjlib/src/pjlib-test/sock_perf.c
+++ b/pjlib/src/pjlib-test/sock_perf.c
@@ -69,8 +69,8 @@ static int sock_producer_consumer(int sock_type,
}
/* Create buffers. */
- outgoing_buffer = pj_pool_alloc(pool, buf_size);
- incoming_buffer = pj_pool_alloc(pool, buf_size);
+ outgoing_buffer = (char*) pj_pool_alloc(pool, buf_size);
+ incoming_buffer = (char*) pj_pool_alloc(pool, buf_size);
/* Start loop. */
pj_get_timestamp(&start);
diff --git a/pjlib/src/pjlib-test/string.c b/pjlib/src/pjlib-test/string.c
index dd3649cc..d8bc54fd 100644
--- a/pjlib/src/pjlib-test/string.c
+++ b/pjlib/src/pjlib-test/string.c
@@ -236,6 +236,9 @@ static int stricmp_test(void)
//return -700;
}
+ /* Avoid division by zero */
+ if (c2 == 0) c2=1;
+
PJ_LOG(3, ("", " time: stricmp=%u, stricmp_alnum=%u (speedup=%d.%02dx)",
c1, c2,
(c1 * 100 / c2) / 100,
@@ -328,7 +331,7 @@ int string_test(void)
/*
* pj_strcpy(), pj_strcat()
*/
- s3.ptr = pj_pool_alloc(pool, 256);
+ s3.ptr = (char*) pj_pool_alloc(pool, 256);
if (!s3.ptr)
return -200;
pj_strcpy(&s3, &s2);
@@ -348,7 +351,7 @@ int string_test(void)
/*
* pj_utoa()
*/
- s5.ptr = pj_pool_alloc(pool, 16);
+ s5.ptr = (char*) pj_pool_alloc(pool, 16);
if (!s5.ptr)
return -270;
s5.slen = pj_utoa(UL_VALUE, s5.ptr);
@@ -392,7 +395,7 @@ int string_test(void)
for (i=0; i<RCOUNT; ++i) {
int j;
- random[i].ptr = pj_pool_alloc(pool, RLEN);
+ random[i].ptr = (char*) pj_pool_alloc(pool, RLEN);
if (!random[i].ptr)
return -320;
diff --git a/pjlib/src/pjlib-test/test.h b/pjlib/src/pjlib-test/test.h
index ab86eacc..b30ba9f5 100644
--- a/pjlib/src/pjlib-test/test.h
+++ b/pjlib/src/pjlib-test/test.h
@@ -21,13 +21,21 @@
#include <pj/types.h>
-#define GROUP_LIBC 1
-#define GROUP_OS 1
-#define GROUP_DATA_STRUCTURE 1
+#define GROUP_LIBC 0
+#define GROUP_OS 0
+#define GROUP_DATA_STRUCTURE 0
#define GROUP_NETWORK 1
-#define GROUP_FILE 1
-
-#define INCLUDE_ERRNO_TEST GROUP_LIBC
+#if defined(PJ_SYMBIAN)
+# define GROUP_FILE 0
+#else
+# define GROUP_FILE 1
+#endif
+
+#if defined(PJ_SYMBIAN)
+# define INCLUDE_ERRNO_TEST 0
+#else
+# define INCLUDE_ERRNO_TEST GROUP_LIBC
+#endif
#define INCLUDE_TIMESTAMP_TEST GROUP_OS
#define INCLUDE_EXCEPTION_TEST GROUP_LIBC
#define INCLUDE_RAND_TEST GROUP_LIBC
@@ -39,16 +47,20 @@
#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_MUTEX_TEST (PJ_HAS_THREADS && GROUP_OS)
#define INCLUDE_SLEEP_TEST GROUP_OS
-#define INCLUDE_THREAD_TEST GROUP_OS
+#define INCLUDE_THREAD_TEST (PJ_HAS_THREADS && GROUP_OS)
#define INCLUDE_SOCK_TEST GROUP_NETWORK
-#define INCLUDE_SOCK_PERF_TEST GROUP_NETWORK
+#if defined(PJ_SYMBIAN)
+# define INCLUDE_SOCK_PERF_TEST 0
+#else
+# define INCLUDE_SOCK_PERF_TEST GROUP_NETWORK
+#endif
#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_IOQUEUE_UNREG_TEST GROUP_NETWORK
+#define INCLUDE_IOQUEUE_PERF_TEST (PJ_HAS_THREADS && GROUP_NETWORK)
+#define INCLUDE_IOQUEUE_UNREG_TEST (PJ_HAS_THREADS && GROUP_NETWORK)
#define INCLUDE_FILE_TEST GROUP_FILE
#define INCLUDE_ECHO_SERVER 0
diff --git a/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c b/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c
index 0e29bbd2..d2d2246a 100644
--- a/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c
+++ b/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c
@@ -117,7 +117,7 @@ static void on_write_complete(pj_ioqueue_key_t *key,
static int worker_thread(void *arg)
{
- pj_ioqueue_t *ioqueue = arg;
+ pj_ioqueue_t *ioqueue = (pj_ioqueue_t*) arg;
struct op_key read_op, write_op;
char recv_buf[512], send_buf[512];
pj_ssize_t length;