Index: /pjproject/branches/symbian/pjlib/include/pj/compat/setjmp.h
===================================================================
--- /pjproject/branches/symbian/pjlib/include/pj/compat/setjmp.h	(revision 787)
+++ /pjproject/branches/symbian/pjlib/include/pj/compat/setjmp.h	(revision 788)
@@ -79,4 +79,6 @@
 # endif   /* _ASM */
 
+#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
+    /* Symbian framework don't use setjmp/longjmp */
 #else
 #  warning "setjmp()/longjmp() is not implemented"
Index: /pjproject/branches/symbian/pjlib/include/pj/errno.h
===================================================================
--- /pjproject/branches/symbian/pjlib/include/pj/errno.h	(revision 787)
+++ /pjproject/branches/symbian/pjlib/include/pj/errno.h	(revision 788)
@@ -190,4 +190,16 @@
 
 /**
+ * Use this macro to generate error message text for your error code,
+ * so that they look uniformly as the rest of the libraries.
+ *
+ * @param code	The error code
+ * @param msg	The error test.
+ */
+#ifndef PJ_BUILD_ERR
+#   define PJ_BUILD_ERR(code,msg) { code, msg " (" #code ")" }
+#endif
+
+
+/**
  * @hideinitializer
  * Unknown error has been reported.
@@ -285,4 +297,9 @@
  */
 #define PJ_ERRNO_SPACE_SIZE	50000
+
+/**
+ * See errno.c.
+ */
+#define PJ_ERRNO_SPACE_GAP	10000
 
 /**
Index: /pjproject/branches/symbian/pjlib/include/pj/except.h
===================================================================
--- /pjproject/branches/symbian/pjlib/include/pj/except.h	(revision 787)
+++ /pjproject/branches/symbian/pjlib/include/pj/except.h	(revision 788)
@@ -238,5 +238,29 @@
 #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
+
 /*****************************************************************************
  **
Index: /pjproject/branches/symbian/pjlib/src/pj/addr_resolv_symbian.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/addr_resolv_symbian.cpp	(revision 788)
+++ /pjproject/branches/symbian/pjlib/src/pj/addr_resolv_symbian.cpp	(revision 788)
@@ -0,0 +1,79 @@
+/* $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/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;
+    TInt rc = resv.GetByName(data, nameEntry);
+
+    if (rc != KErrNone)
+	return PJ_RETURN_OS_ERROR(rc);
+
+    // Get the resolved TInetAddr
+    const TNameRecord &rec = (const TNameRecord&) nameEntry;
+    TInetAddr inetAddr(rec.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(rec.iName.Ptr(), rec.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;
+}
+
Index: /pjproject/branches/symbian/pjlib/src/pj/compat/string_compat.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/compat/string_compat.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pj/compat/string_compat.c	(revision 788)
@@ -52,6 +52,8 @@
 {
     int ret;
-    
     va_list arg;
+
+    PJ_UNUSED_ARG(len);
+
     va_start(arg, s2);
     ret = vsprintf(s1, s2, arg);
@@ -63,4 +65,5 @@
 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);
 }
Index: /pjproject/branches/symbian/pjlib/src/pj/errno.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/errno.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pj/errno.c	(revision 788)
@@ -141,11 +141,11 @@
     pj_assert(buf && bufsize);
 
-    if (statcode < PJ_ERRNO_START + PJ_ERRNO_SPACE_SIZE) {
+    if (statcode < PJ_ERRNO_START + PJ_ERRNO_SPACE_SIZE - PJ_ERRNO_SPACE_GAP) {
         len = pj_ansi_snprintf( buf, bufsize, "Unknown error %d", statcode);
 
-    } else if (statcode < PJ_ERRNO_START_STATUS + PJ_ERRNO_SPACE_SIZE) {
+    } else if (statcode < PJ_ERRNO_START_STATUS + PJ_ERRNO_SPACE_SIZE - PJ_ERRNO_SPACE_GAP) {
         len = pjlib_error(statcode, buf, bufsize);
 
-    } else if (statcode < PJ_ERRNO_START_SYS + PJ_ERRNO_SPACE_SIZE) {
+    } else if (statcode < PJ_ERRNO_START_SYS + PJ_ERRNO_SPACE_SIZE - PJ_ERRNO_SPACE_GAP) {
         len = platform_strerror(PJ_STATUS_TO_OS(statcode), buf, bufsize);
 
Index: /pjproject/branches/symbian/pjlib/src/pj/exception_symbian.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/exception_symbian.cpp	(revision 788)
+++ /pjproject/branches/symbian/pjlib/src/pj/exception_symbian.cpp	(revision 788)
@@ -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 */
+
+
+
Index: /pjproject/branches/symbian/pjlib/src/pj/ioqueue_symbian.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/ioqueue_symbian.cpp	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pj/ioqueue_symbian.cpp	(revision 788)
@@ -18,4 +18,291 @@
  */
 #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:
+    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), cb_(cb), 
+	  user_data_(user_data), aBufferPtr_(NULL, 0), type_(TYPE_NONE)
+    {
+	CActiveScheduler::Add(this);
+    }
+
+    //
+    // 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)
+    {
+	PJ_ASSERT_RETURN(IsActive()==false, PJ_EBUSY);
+	PJ_ASSERT_RETURN(pending_data_.common_.op_key_==NULL, PJ_EBUSY);
+
+	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;
+	SetActive();
+	sock_->Socket().RecvFrom(aBufferPtr_, aAddress_, flags, iStatus);
+
+	return PJ_EPENDING;
+    }
+
+
+    //
+    // 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 )
+    {
+	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;
+	SetActive();
+	sock_->Socket().Accept(blank_sock_, iStatus);
+
+	return PJ_EPENDING;
+    }
+
+
+    //
+    // Completion callback.
+    //
+    void 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) {
+		cb_->on_read_complete(key_, op_key, -PJ_RETURN_OS_ERROR(iStatus.Int()));
+		return;
+	    }
+
+	    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;
+	    }
+
+	    /* Call callback */
+	    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;
+
+		cb_->on_accept_complete(key_, op_key, PJ_INVALID_SOCKET,
+					-PJ_RETURN_OS_ERROR(iStatus.Int()));
+		return;
+	    }
+
+	    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;
+		blank_sock_.LocalName(aAddr);
+		PjSymbianOS::Addr2pj(aAddr, *(pj_sockaddr_in*)pending_data_.accept_.local_);
+		pending_data_.accept_.local_ = NULL;
+	    }
+
+	    if (pending_data_.accept_.remote_) {
+		TInetAddr aAddr;
+		blank_sock_.RemoteName(aAddr);
+		PjSymbianOS::Addr2pj(aAddr, *(pj_sockaddr_in*)pending_data_.accept_.remote_);
+		pending_data_.accept_.remote_ = NULL;
+	    }
+
+	    if (pending_data_.accept_.addrlen_) {
+		*pending_data_.accept_.addrlen_ = sizeof(pj_sockaddr_in);
+		pending_data_.accept_.addrlen_ = NULL;
+	    }
+
+	    // Call callback.
+	    cb_->on_accept_complete(key_, op_key, (pj_sock_t)pjNewSock, PJ_SUCCESS);
+	}
+
+	ioqueue_->eventCount++;
+    }
+
+    //
+    // CActive's DoCancel()
+    //
+    void 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 CancelOperation(pj_ioqueue_op_key_t *op_key, pj_ssize_t bytes_status)
+    {
+	Type cur_type = type_;
+
+	Cancel();
+
+	if (cur_type == TYPE_READ)
+	    cb_->on_read_complete(key_, op_key, bytes_status);
+	else if (cur_type == TYPE_ACCEPT)
+	    ;
+    }
+
+    //
+    // 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_;
+    const 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_;
+};
+
+
+
+
+/*
+ * IO Queue key structure.
+ */
+struct pj_ioqueue_key_t
+{
+    CIoqueueCallback	*cbObj;
+};
 
 
@@ -25,5 +312,336 @@
 PJ_DEF(const char*) pj_ioqueue_name(void)
 {
-    return "symbian";
-}
-
+    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_alloc(pool, sizeof(pj_ioqueue_key_t));
+    key->cbObj = new CIoqueueCallback(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;
+
+    // Close socket.
+    key->cbObj->get_pj_socket()->Socket().Close();
+    delete key->cbObj->get_pj_socket();
+
+    // Delete async object
+    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())
+	    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->HasTimedOut());
+
+    if (!timer->HasTimedOut())
+	timer->Cancel();
+
+    if (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 )
+{
+    return pj_ioqueue_recvfrom(key, 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;
+
+    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);
+
+    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());
+
+    *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);
+
+    aBuffer.Set((const TUint8*)data, (TInt)*length);
+    PjSymbianOS::pj2Addr(*(const pj_sockaddr_in*)addr, inetAddr);
+    CPjSocket *pjSock = key->cbObj->get_pj_socket();
+
+    pjSock->Socket().Send(aBuffer, flags, reqStatus, aLen);
+    User::WaitForRequest(reqStatus);
+
+    if (reqStatus.Int() != KErrNone)
+	return PJ_RETURN_OS_ERROR(reqStatus.Int());
+
+    *length = aLen.Length();
+    return PJ_SUCCESS;
+}
+
Index: /pjproject/branches/symbian/pjlib/src/pj/log.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/log.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pj/log.c	(revision 788)
@@ -151,5 +151,5 @@
 	    log_buffer[len++] = '\n';
 	}
-	log_buffer[len++] = '\0';
+	log_buffer[len] = '\0';
     } else {
 	len = sizeof(log_buffer)-1;
Index: /pjproject/branches/symbian/pjlib/src/pj/log_writer_symbian_console.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/log_writer_symbian_console.cpp	(revision 788)
+++ /pjproject/branches/symbian/pjlib/src/pj/log_writer_symbian_console.cpp	(revision 788)
@@ -0,0 +1,43 @@
+/* $Id: log_writer_stdout.c 66 2005-11-21 02:08:39Z bennylp $ */
+/* 
+ * 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
+}
+
Index: /pjproject/branches/symbian/pjlib/src/pj/os_core_symbian.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/os_core_symbian.cpp	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pj/os_core_symbian.cpp	(revision 788)
@@ -18,7 +18,4 @@
  */
 
-#include <e32cmn.h>
-#include <e32std.h>
-
 #include <pj/os.h>
 #include <pj/assert.h>
@@ -31,10 +28,12 @@
 #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:
@@ -61,4 +60,181 @@
 
 
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// CPjTimeoutTimer implementation
+//
+
+CPjTimeoutTimer::CPjTimeoutTimer()
+: CActive(EPriorityNormal), hasTimedOut_(false)
+{
+}
+
+CPjTimeoutTimer::~CPjTimeoutTimer()
+{
+    if (IsActive())
+	Cancel();
+    timer_.Close();
+}
+
+void CPjTimeoutTimer::ConstructL()
+{
+    timer_.CreateLocal();
+    CActiveScheduler::Add(this);
+}
+
+CPjTimeoutTimer *CPjTimeoutTimer::NewL()
+{
+    CPjTimeoutTimer *self = new (ELeave) CPjTimeoutTimer;
+    CleanupStack::PushL(self);
+
+    self->ConstructL();
+
+    CleanupStack::Pop(self);
+    return self;
+
+}
+
+void CPjTimeoutTimer::StartTimer(TUint miliSeconds)
+{
+    if (IsActive())
+	Cancel();
+
+    hasTimedOut_ = false;
+    timer_.After(iStatus, miliSeconds * 1000);
+    SetActive();
+}
+
+bool CPjTimeoutTimer::HasTimedOut() const
+{
+    return hasTimedOut_;
+}
+
+void CPjTimeoutTimer::RunL()
+{
+    hasTimedOut_ = 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)
 {
@@ -66,4 +242,6 @@
 }
 
+
+PJ_DECL(void) pj_shutdown(void);
 
 /*
@@ -74,5 +252,42 @@
 {
     pj_ansi_strcpy(main_thread.obj_name, "pjthread");
-    return PJ_SUCCESS;
+
+    // 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(void) pj_shutdown(void)
+{
+    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;
 }
 
@@ -150,8 +365,6 @@
 PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec)
 {
-    PJ_UNUSED_ARG(msec);
-
-    /* Not supported either */
-    return PJ_EINVALIDOP;
+    User::After(msec*1000);
+    return PJ_SUCCESS;
 }
 
Index: /pjproject/branches/symbian/pjlib/src/pj/os_error_symbian.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/os_error_symbian.cpp	(revision 788)
+++ /pjproject/branches/symbian/pjlib/src/pj/os_error_symbian.cpp	(revision 788)
@@ -0,0 +1,168 @@
+/* $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);
+}
+
+extern "C" int platform_strerror( pj_os_err_type os_errcode, 
+                       		  char *buf, pj_size_t bufsize);
+
+/* 
+ * platform_strerror()
+ *
+ * Platform specific error message. This file is called by pj_strerror() 
+ * in errno.c 
+ */
+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;
+}
+
Index: /pjproject/branches/symbian/pjlib/src/pj/os_symbian.h
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/os_symbian.h	(revision 788)
+++ /pjproject/branches/symbian/pjlib/src/pj/os_symbian.h	(revision 788)
@@ -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_;
+    bool   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;
+	CActiveScheduler::RunIfReady(aError, aPriority);
+    }
+
+private:
+    bool isSocketServInitialized_;
+    RSocketServ socketServ_;
+
+    bool isResolverInitialized_;
+    RHostResolver hostResolver_;
+
+    CConsoleBase* console_;
+
+    CPjTimeoutTimer *selectTimeoutTimer_;
+
+private:
+    PjSymbianOS();
+    
+};
+
+
+#endif	/* __OS_SYMBIAN_H__ */
+
Index: /pjproject/branches/symbian/pjlib/src/pj/pool.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/pool.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pj/pool.c	(revision 788)
@@ -19,5 +19,4 @@
 #include <pj/pool.h>
 #include <pj/log.h>
-#include <pj/except.h>
 #include <pj/assert.h>
 #include <pj/os.h>
Index: /pjproject/branches/symbian/pjlib/src/pj/pool_policy_new.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/pool_policy_new.cpp	(revision 788)
+++ /pjproject/branches/symbian/pjlib/src/pj/pool_policy_new.cpp	(revision 788)
@@ -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 */
+
Index: /pjproject/branches/symbian/pjlib/src/pj/sock_bsd.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/sock_bsd.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pj/sock_bsd.c	(revision 788)
@@ -633,4 +633,6 @@
     PJ_ASSERT_RETURN(newsock != NULL, PJ_EINVAL);
 
+    hello
+
 #if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
     if (addr) {
Index: /pjproject/branches/symbian/pjlib/src/pj/sock_select_symbian.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/sock_select_symbian.cpp	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pj/sock_select_symbian.cpp	(revision 788)
@@ -18,9 +18,21 @@
  */
 #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)
 {
-    PJ_TODO(PJ_FD_ZERO);
+    symbian_fd_set *fds = (symbian_fd_set *)fdsetp;
+    fds->count = 0;
 }
 
@@ -28,5 +40,8 @@
 PJ_DEF(void) PJ_FD_SET(pj_sock_t fd, pj_fd_set_t *fdsetp)
 {
-    PJ_TODO(PJ_FD_SET);
+    symbian_fd_set *fds = (symbian_fd_set *)fdsetp;
+
+    PJ_ASSERT_ON_FAIL(fds->count < FD_SETSIZE, return);
+    fds->sock[fds->count++] = (CPjSocket*)fd;
 }
 
@@ -34,5 +49,14 @@
 PJ_DEF(void) PJ_FD_CLR(pj_sock_t fd, pj_fd_set_t *fdsetp)
 {
-    PJ_TODO(PJ_FD_CLR);
+    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;
+	}
+    }
 }
 
@@ -40,13 +64,22 @@
 PJ_DEF(pj_bool_t) PJ_FD_ISSET(pj_sock_t fd, const pj_fd_set_t *fdsetp)
 {
-    PJ_TODO(PJ_FD_ISSET);
-    return 0;
+    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)
 {
-    PJ_TODO(PJ_FD_COUNT);
-    return 0;
+    symbian_fd_set *fds = (symbian_fd_set *)fdsetp;
+    return fds->count;
 }
+
 
 PJ_DEF(int) pj_sock_select( int n, 
@@ -56,5 +89,73 @@
 			    const pj_time_val *timeout)
 {
-    PJ_TODO(pj_sock_select);
+    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;
 }
Index: /pjproject/branches/symbian/pjlib/src/pj/sock_symbian.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/sock_symbian.cpp	(revision 788)
+++ /pjproject/branches/symbian/pjlib/src/pj/sock_symbian.cpp	(revision 788)
@@ -0,0 +1,933 @@
+/* $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();
+
+    // Socket must be connected.
+    PJ_ASSERT_RETURN(pjSock->IsConnected(), PJ_EINVALIDOP);
+
+    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)->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)->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 */
+
+
Index: /pjproject/branches/symbian/pjlib/src/pj/unicode_symbian.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pj/unicode_symbian.cpp	(revision 788)
+++ /pjproject/branches/symbian/pjlib/src/pj/unicode_symbian.cpp	(revision 788)
@@ -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;
+}
+
+
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/atomic.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/atomic.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/atomic.c	(revision 788)
@@ -18,5 +18,5 @@
  */
 #include "test.h"
-#include <pjlib.h>
+#include <pj/os.h>
 
 /**
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/echo_clt.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/echo_clt.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/echo_clt.c	(revision 788)
@@ -18,5 +18,6 @@
  */
 #include "test.h"
-#include <pjlib.h>
+#include <pj/os.h>
+#include <pj/sock.h>
 
 #if INCLUDE_ECHO_CLIENT
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/file.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/file.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/file.c	(revision 788)
@@ -18,5 +18,7 @@
  */
 #include "test.h"
-#include <pjlib.h>
+#include <pj/file_io.h>
+#include <pj/file_access.h>
+
 
 #if INCLUDE_FILE_TEST
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/ioq_perf.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/ioq_perf.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/ioq_perf.c	(revision 788)
@@ -18,5 +18,10 @@
  */
 #include "test.h"
-#include <pjlib.h>
+#include <pj/errno.h>
+#include <pj/ioqueue.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/pool.h>
+#include <pj/sock.h>
 #include <pj/compat/high_precision.h>
 
@@ -73,5 +78,5 @@
                              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;
@@ -151,5 +156,5 @@
                               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));
@@ -189,5 +194,5 @@
 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;
@@ -250,6 +255,6 @@
         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.."));
@@ -266,6 +271,6 @@
         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;
 
@@ -332,5 +337,5 @@
 	struct thread_arg *arg;
 
-	arg = pj_pool_zalloc(pool, sizeof(*arg));
+	arg = (struct thread_arg *)pj_pool_zalloc(pool, sizeof(*arg));
 	arg->id = i;
 	arg->ioqueue = ioqueue;
@@ -444,4 +449,9 @@
     enum { BUF_SIZE = 512 };
     int i, rc;
+    enum
+    {
+	SOCK_DGRAM = 1,
+	SOCK_STREAM = 2,
+    };
     struct {
         int         type;
@@ -451,47 +461,47 @@
     } test_param[] = 
     {
-        { PJ_SOCK_DGRAM, "udp", 1, 1},
-        { PJ_SOCK_DGRAM, "udp", 1, 2},
-        { PJ_SOCK_DGRAM, "udp", 1, 4},
-        { PJ_SOCK_DGRAM, "udp", 1, 8},
-        { PJ_SOCK_DGRAM, "udp", 2, 1},
-        { PJ_SOCK_DGRAM, "udp", 2, 2},
-        { PJ_SOCK_DGRAM, "udp", 2, 4},
-        { PJ_SOCK_DGRAM, "udp", 2, 8},
-        { PJ_SOCK_DGRAM, "udp", 4, 1},
-        { PJ_SOCK_DGRAM, "udp", 4, 2},
-        { PJ_SOCK_DGRAM, "udp", 4, 4},
-        { PJ_SOCK_DGRAM, "udp", 4, 8},
-        { PJ_SOCK_DGRAM, "udp", 4, 16},
-        { PJ_SOCK_STREAM, "tcp", 1, 1},
-        { PJ_SOCK_STREAM, "tcp", 1, 2},
-        { PJ_SOCK_STREAM, "tcp", 1, 4},
-        { PJ_SOCK_STREAM, "tcp", 1, 8},
-        { PJ_SOCK_STREAM, "tcp", 2, 1},
-        { PJ_SOCK_STREAM, "tcp", 2, 2},
-        { PJ_SOCK_STREAM, "tcp", 2, 4},
-        { PJ_SOCK_STREAM, "tcp", 2, 8},
-        { PJ_SOCK_STREAM, "tcp", 4, 1},
-        { PJ_SOCK_STREAM, "tcp", 4, 2},
-        { PJ_SOCK_STREAM, "tcp", 4, 4},
-        { PJ_SOCK_STREAM, "tcp", 4, 8},
-        { PJ_SOCK_STREAM, "tcp", 4, 16},
+        { SOCK_DGRAM, "udp", 1, 1},
+        { SOCK_DGRAM, "udp", 1, 2},
+        { SOCK_DGRAM, "udp", 1, 4},
+        { SOCK_DGRAM, "udp", 1, 8},
+        { SOCK_DGRAM, "udp", 2, 1},
+        { SOCK_DGRAM, "udp", 2, 2},
+        { SOCK_DGRAM, "udp", 2, 4},
+        { SOCK_DGRAM, "udp", 2, 8},
+        { SOCK_DGRAM, "udp", 4, 1},
+        { SOCK_DGRAM, "udp", 4, 2},
+        { SOCK_DGRAM, "udp", 4, 4},
+        { SOCK_DGRAM, "udp", 4, 8},
+        { SOCK_DGRAM, "udp", 4, 16},
+        { SOCK_STREAM, "tcp", 1, 1},
+        { SOCK_STREAM, "tcp", 1, 2},
+        { SOCK_STREAM, "tcp", 1, 4},
+        { SOCK_STREAM, "tcp", 1, 8},
+        { SOCK_STREAM, "tcp", 2, 1},
+        { SOCK_STREAM, "tcp", 2, 2},
+        { SOCK_STREAM, "tcp", 2, 4},
+        { SOCK_STREAM, "tcp", 2, 8},
+        { SOCK_STREAM, "tcp", 4, 1},
+        { SOCK_STREAM, "tcp", 4, 2},
+        { SOCK_STREAM, "tcp", 4, 4},
+        { SOCK_STREAM, "tcp", 4, 8},
+        { SOCK_STREAM, "tcp", 4, 16},
 /*
-	{ PJ_SOCK_DGRAM, "udp", 32, 1},
-	{ PJ_SOCK_DGRAM, "udp", 32, 1},
-	{ PJ_SOCK_DGRAM, "udp", 32, 1},
-	{ PJ_SOCK_DGRAM, "udp", 32, 1},
-	{ PJ_SOCK_DGRAM, "udp", 1, 32},
-	{ PJ_SOCK_DGRAM, "udp", 1, 32},
-	{ PJ_SOCK_DGRAM, "udp", 1, 32},
-	{ PJ_SOCK_DGRAM, "udp", 1, 32},
-	{ PJ_SOCK_STREAM, "tcp", 32, 1},
-	{ PJ_SOCK_STREAM, "tcp", 32, 1},
-	{ PJ_SOCK_STREAM, "tcp", 32, 1},
-	{ PJ_SOCK_STREAM, "tcp", 32, 1},
-	{ PJ_SOCK_STREAM, "tcp", 1, 32},
-	{ PJ_SOCK_STREAM, "tcp", 1, 32},
-	{ PJ_SOCK_STREAM, "tcp", 1, 32},
-	{ PJ_SOCK_STREAM, "tcp", 1, 32},
+	{ SOCK_DGRAM, "udp", 32, 1},
+	{ SOCK_DGRAM, "udp", 32, 1},
+	{ SOCK_DGRAM, "udp", 32, 1},
+	{ SOCK_DGRAM, "udp", 32, 1},
+	{ SOCK_DGRAM, "udp", 1, 32},
+	{ SOCK_DGRAM, "udp", 1, 32},
+	{ SOCK_DGRAM, "udp", 1, 32},
+	{ SOCK_DGRAM, "udp", 1, 32},
+	{ SOCK_STREAM, "tcp", 32, 1},
+	{ SOCK_STREAM, "tcp", 32, 1},
+	{ SOCK_STREAM, "tcp", 32, 1},
+	{ SOCK_STREAM, "tcp", 32, 1},
+	{ SOCK_STREAM, "tcp", 1, 32},
+	{ SOCK_STREAM, "tcp", 1, 32},
+	{ SOCK_STREAM, "tcp", 1, 32},
+	{ SOCK_STREAM, "tcp", 1, 32},
 */
     };
@@ -503,4 +513,11 @@
     PJ_LOG(3,(THIS_FILE, "   Type  Threads  Skt.Pairs      Bandwidth"));
     PJ_LOG(3,(THIS_FILE, "   ======================================="));
+
+    for (i=0; i<PJ_ARRAY_SIZE(test_param); ++i) {
+	if (test_param[i].type == SOCK_DGRAM)
+	    test_param[i].type = PJ_SOCK_DGRAM;
+	else if (test_param[i].type == SOCK_STREAM)
+	    test_param[i].type = PJ_SOCK_STREAM;
+    }
 
     best_bandwidth = 0;
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/ioq_tcp.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/ioq_tcp.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/ioq_tcp.c	(revision 788)
@@ -34,5 +34,12 @@
 #if INCLUDE_TCP_IOQUEUE_TEST
 
-#include <pjlib.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/ioqueue.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+#include <pj/sock.h>
+#include <pj/string.h>
+
 
 #if PJ_HAS_TCP
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/ioq_udp.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/ioq_udp.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/ioq_udp.c	(revision 788)
@@ -35,5 +35,13 @@
 #if INCLUDE_UDP_IOQUEUE_TEST
 
-#include <pjlib.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/ioqueue.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/pool.h>
+#include <pj/sock.h>
+#include <pj/string.h>
+
 
 #include <pj/compat/socket.h>
@@ -329,5 +337,5 @@
                              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);
@@ -511,6 +519,6 @@
 	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 */
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/main_symbian.cpp
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/main_symbian.cpp	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/main_symbian.cpp	(revision 788)
@@ -7,4 +7,29 @@
 
 #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>
 
@@ -13,10 +38,4 @@
 #include <e32cons.h>            // Console
 
-
-//  Constants
-
-_LIT(KTextConsoleTitle, "Console");
-_LIT(KTextFailed, " failed, leave code = %d");
-_LIT(KTextPressAnyKey, " [press any key]\n");
 
 
@@ -29,10 +48,85 @@
 
 LOCAL_C void MainL()
-    {
+{
     //
     // add your program code here, example code below
     //
     test_main();
-    }
+    CActiveScheduler::Stop();
+}
+
+class MyScheduler : public CActiveScheduler
+{
+public:
+    MyScheduler()
+    {}
+
+    void Error(TInt aError) const;
+};
+
+void MyScheduler::Error(TInt aError) const
+{
+    int i = 0;
+}
+
+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;
+}
 
 
@@ -40,16 +134,32 @@
     {
     // Create active scheduler (to run active objects)
-    CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
+    CActiveScheduler* scheduler = new (ELeave) MyScheduler;
     CleanupStack::PushL(scheduler);
     CActiveScheduler::Install(scheduler);
 
-    MainL();
+    ProgramStarter *starter = ProgramStarter::NewL();
+    starter->Start();
+
+    CActiveScheduler::Start();
 
     // Delete active scheduler
-    CleanupStack::PopAndDestroy(scheduler);
+    //CActiveScheduler::Install(NULL);
+    scheduler->Stop();
+    //delete scheduler;
     }
 
 
 //  Global Functions
+
+static void log_writer(int level, const char *buf, int len)
+{
+    wchar_t buf16[PJ_LOG_MAX_SIZE];
+
+    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()
@@ -60,13 +170,15 @@
 
     // Create output console
-    TRAPD(createError, console = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen,KConsFullScreen)));
+    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(KTextFailed, mainError);
-    console->Printf(KTextPressAnyKey);
+        console->Printf(_L(" failed, leave code = %d"), mainError);
+    console->Printf(_L(" [press any key]\n"));
     console->Getch();
     
@@ -76,2 +188,5 @@
     return KErrNone;
     }
+
+#endif	/* if 0 */
+
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/mutex.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/mutex.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/mutex.c	(revision 788)
@@ -18,5 +18,6 @@
  */
 #include "test.h"
-#include <pjlib.h>
+#include <pj/errno.h>
+#include <pj/os.h>
 
 #if INCLUDE_MUTEX_TEST
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/rand.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/rand.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/rand.c	(revision 788)
@@ -23,5 +23,10 @@
 #if INCLUDE_RAND_TEST
 
-#define COUNT  1024
+#if defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
+#   define COUNT    128
+#else
+#   define COUNT  1024
+#endif
+
 static int values[COUNT];
 
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/select.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/select.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/select.c	(revision 788)
@@ -72,5 +72,5 @@
     }
 
-    timeout.sec = 1;
+    timeout.sec = 5;
     timeout.msec = 0;
 
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/sock.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/sock.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/sock.c	(revision 788)
@@ -17,5 +17,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  */
-#include <pjlib.h>
+#include <pj/errno.h>
+#include <pj/ioqueue.h>
+#include <pj/log.h>
+#include <pj/sock.h>
+#include <pj/string.h>
 #include "test.h"
 
@@ -65,8 +69,4 @@
 #define BIG_DATA_LEN	9000
 #define ADDRESS		"127.0.0.1"
-#define A0		127
-#define A1		0
-#define A2		0
-#define A3		1
 
 
@@ -80,4 +80,10 @@
     pj_in_addr addr;
     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()"));
@@ -89,5 +95,5 @@
     /* 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, 
@@ -97,9 +103,9 @@
 
     /* pj_inet_ntoa() */
-    p = pj_inet_ntoa(addr);
+    p = (unsigned char*)pj_inet_ntoa(addr);
     if (!p)
 	return -20;
 
-    if (pj_strcmp2(&s, p) != 0)
+    if (pj_strcmp2(&s, (char*)p) != 0)
 	return -30;
 
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/sock_perf.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/sock_perf.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/sock_perf.c	(revision 788)
@@ -18,5 +18,10 @@
  */
 #include "test.h"
-#include <pjlib.h>
+#include <pj/errno.h>
+#include <pj/ioqueue.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/pool.h>
+#include <pj/sock.h>
 #include <pj/compat/high_precision.h>
 
@@ -70,6 +75,6 @@
 
     /* 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. */
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/string_test.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/string_test.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/string_test.c	(revision 788)
@@ -284,6 +284,6 @@
 int string_test(void)
 {
-    const pj_str_t hello_world = { HELLO_WORLD, strlen(HELLO_WORLD) };
-    const pj_str_t just_hello = { JUST_HELLO, strlen(JUST_HELLO) };
+    pj_str_t hello_world;
+    pj_str_t just_hello;
     pj_str_t s1, s2, s3, s4, s5;
     enum { RCOUNT = 10, RLEN = 16 };
@@ -291,4 +291,7 @@
     pj_pool_t *pool;
     int i;
+
+    hello_world = pj_str(HELLO_WORLD);
+    just_hello = pj_str(JUST_HELLO);
 
     pool = pj_pool_create(mem, NULL, 4096, 0, NULL);
@@ -328,5 +331,5 @@
      * pj_strcpy(), pj_strcat() 
      */
-    s3.ptr = pj_pool_alloc(pool, 256);
+    s3.ptr = (char*)pj_pool_alloc(pool, 256);
     if (!s3.ptr) 
 	return -200;
@@ -348,5 +351,5 @@
      * pj_utoa() 
      */
-    s5.ptr = pj_pool_alloc(pool, 16);
+    s5.ptr = (char*)pj_pool_alloc(pool, 16);
     if (!s5.ptr)
 	return -270;
@@ -366,5 +369,5 @@
 	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;
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/test.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/test.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/test.c	(revision 788)
@@ -18,5 +18,11 @@
  */
 #include "test.h"
-#include <pjlib.h>
+#include <pj/errno.h>
+#include <pj/ioqueue.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/pool.h>
+#include <pj/sock.h>
+
 #ifdef _MSC_VER
 #  pragma warning(disable:4127)
@@ -195,16 +201,4 @@
 int test_main(void)
 {
-    PJ_USE_EXCEPTION;
-
-    PJ_TRY {
-        return test_inner();
-    }
-    PJ_CATCH_ANY {
-        int id = PJ_GET_EXCEPTION();
-        PJ_LOG(3,("test", "FATAL: unhandled exception id %d (%s)", 
-                  id, pj_exception_id_name(id)));
-    }
-    PJ_END;
-
-    return -1;
+    return test_inner();
 }
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/test.h
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/test.h	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/test.h	(revision 788)
@@ -25,8 +25,8 @@
 #define GROUP_OS                    0
 #define GROUP_DATA_STRUCTURE        0
-#define GROUP_NETWORK               0
+#define GROUP_NETWORK               1
 #define GROUP_FILE                  0
 
-#define INCLUDE_ERRNO_TEST          GROUP_LIBC
+#define INCLUDE_ERRNO_TEST          0	// GROUP_LIBC
 #define INCLUDE_TIMESTAMP_TEST      GROUP_OS
 #define INCLUDE_EXCEPTION_TEST	    GROUP_LIBC
@@ -34,16 +34,16 @@
 #define INCLUDE_LIST_TEST	    GROUP_DATA_STRUCTURE
 #define INCLUDE_POOL_TEST	    GROUP_LIBC
-#define INCLUDE_POOL_PERF_TEST	    (PJ_HAS_MALLOC && GROUP_LIBC)
-#define INCLUDE_STRING_TEST	    GROUP_DATA_STRUCTURE
+#define INCLUDE_POOL_PERF_TEST	    0	// (PJ_HAS_MALLOC && GROUP_LIBC)
+#define INCLUDE_STRING_TEST	    0	// GROUP_DATA_STRUCTURE
 #define INCLUDE_FIFOBUF_TEST	    0	// GROUP_DATA_STRUCTURE
 #define INCLUDE_RBTREE_TEST	    GROUP_DATA_STRUCTURE
 #define INCLUDE_TIMER_TEST	    GROUP_DATA_STRUCTURE
 #define INCLUDE_ATOMIC_TEST         GROUP_OS
-#define INCLUDE_MUTEX_TEST	    GROUP_OS
+#define INCLUDE_MUTEX_TEST	    (PJ_HAS_THREADS && GROUP_OS)
 #define INCLUDE_SLEEP_TEST          GROUP_OS
-#define INCLUDE_THREAD_TEST         GROUP_OS
-#define INCLUDE_SOCK_TEST	    GROUP_NETWORK
-#define INCLUDE_SOCK_PERF_TEST      GROUP_NETWORK
-#define INCLUDE_SELECT_TEST	    GROUP_NETWORK
+#define INCLUDE_THREAD_TEST         (PJ_HAS_THREADS && GROUP_OS)
+#define INCLUDE_SOCK_TEST	    0 	// GROUP_NETWORK
+#define INCLUDE_SOCK_PERF_TEST      0	// GROUP_NETWORK
+#define INCLUDE_SELECT_TEST	    0	// GROUP_NETWORK
 #define INCLUDE_UDP_IOQUEUE_TEST    GROUP_NETWORK
 #define INCLUDE_TCP_IOQUEUE_TEST    GROUP_NETWORK
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/timestamp.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/timestamp.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/timestamp.c	(revision 788)
@@ -196,5 +196,5 @@
     }
 
-    sleep(0);
+    pj_thread_sleep(0);
 
     /* Mark end time. */
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/udp_echo_srv_ioqueue.c	(revision 788)
@@ -17,5 +17,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  */
-#include <pjlib.h>
+#include <pj/errno.h>
+#include <pj/ioqueue.h>
+#include <pj/pool.h>
+#include <pj/sock.h>
 #include "test.h"
 
@@ -118,5 +121,5 @@
 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];
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/udp_echo_srv_sync.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/udp_echo_srv_sync.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/udp_echo_srv_sync.c	(revision 788)
@@ -18,5 +18,11 @@
  */
 #include "test.h"
-#include <pjlib.h>
+#include <pj/errno.h>
+#include <pj/ioqueue.h>
+#include <pj/os.h>
+#include <pj/pool.h>
+#include <pj/sock.h>
+#include <pj/compat/high_precision.h>
+
 
 static pj_atomic_t *total_bytes;
Index: /pjproject/branches/symbian/pjlib/src/pjlib-test/util.c
===================================================================
--- /pjproject/branches/symbian/pjlib/src/pjlib-test/util.c	(revision 787)
+++ /pjproject/branches/symbian/pjlib/src/pjlib-test/util.c	(revision 788)
@@ -18,5 +18,10 @@
  */
 #include "test.h"
-#include <pjlib.h>
+#include <pj/errno.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/sock.h>
+#include <pj/string.h>
+
 
 #define THIS_FILE "util.c"
Index: /pjproject/branches/symbian/symbian/ABLD.BAT
===================================================================
--- /pjproject/branches/symbian/symbian/ABLD.BAT	(revision 787)
+++ /pjproject/branches/symbian/symbian/ABLD.BAT	(revision 788)
@@ -4,5 +4,5 @@
 REM ** DO NOT EDIT **
 
-perl -S ABLD.PL "\Project\symbian\symbian\\" %1 %2 %3 %4 %5 %6 %7 %8 %9
+perl -S ABLD.PL "\Project\pjsymbian\symbian\\" %1 %2 %3 %4 %5 %6 %7 %8 %9
 if errorlevel==1 goto CheckPerl
 goto End
Index: /pjproject/branches/symbian/symbian/b.bat
===================================================================
--- /pjproject/branches/symbian/symbian/b.bat	(revision 787)
+++ /pjproject/branches/symbian/symbian/b.bat	(revision 788)
@@ -1,4 +1,7 @@
 rem set MWSym2Libraries=1
 rem set MWSym2Libraries=\Symbian\9.1\S60_3rd\Epoc32\release\winscw\udeb
-set EPOCROOT=\Symbian\9.1\S60_3rd\
-abld build -v winscw udeb
+rem set EPOCROOT=\Symbian\9.1\S60_3rd\
+rem call abld build -v winscw udeb
+
+set EPOCROOT=\Symbian\UIQ3SDK\
+call abld build -v vs6 udeb
Index: /pjproject/branches/symbian/symbian/bld.inf
===================================================================
--- /pjproject/branches/symbian/symbian/bld.inf	(revision 787)
+++ /pjproject/branches/symbian/symbian/bld.inf	(revision 788)
@@ -1,3 +1,3 @@
 prj_mmpfiles
 pjlib.mmp
-pjlib-test.mmp
+pjlib_test.mmp
Index: project/branches/symbian/symbian/pjlib-test.mmp
===================================================================
--- /pjproject/branches/symbian/symbian/pjlib-test.mmp	(revision 787)
+++ 	(revision )
@@ -1,57 +1,0 @@
-TARGET 		pjlib-test-symbian.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
-
-
-// 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_test.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	\symbian\9.1\S60_3rd\epoc32\include
-SYSTEMINCLUDE	\symbian\9.1\S60_3rd\epoc32\include\libc
-//SYSTEMINCLUDE	\symbian\9.1\S60_3rd_MR\epoc32\include
-//SYSTEMINCLUDE	\symbian\9.1\S60_3rd_MR\epoc32\include\libc
-
-LIBRARY		pjlib-symbian.lib euser.lib estlib.lib eexe.lib
-		//eexe.lib 
-CAPABILITY	None
-
Index: /pjproject/branches/symbian/symbian/pjlib.mmp
===================================================================
--- /pjproject/branches/symbian/symbian/pjlib.mmp	(revision 787)
+++ /pjproject/branches/symbian/symbian/pjlib.mmp	(revision 788)
@@ -1,3 +1,3 @@
-TARGET 		pjlib-symbian.lib
+TARGET 		pjlib.lib
 TARGETTYPE 	lib
 UID		0x100039CE 0x10004299
@@ -17,5 +17,4 @@
 SOURCE		ctype.c
 SOURCE		errno.c
-SOURCE		except.c
 SOURCE		fifobuf.c
 SOURCE		guid.c
@@ -37,24 +36,24 @@
 // Platform dependent source
 //
-SOURCE		addr_resolv_sock.c
+SOURCE		addr_resolv_symbian.cpp
+SOURCE		exception_symbian.cpp
 SOURCE		file_access_unistd.c
 SOURCE		file_io_ansi.c
 SOURCE		guid_simple.c
-SOURCE		log_writer_stdout.c
+SOURCE		log_writer_symbian_console.cpp
 SOURCE		os_core_symbian.cpp
-SOURCE		os_error_unix.c
+SOURCE		os_error_symbian.cpp
+SOURCE		os_timestamp_common.c
 SOURCE		os_time_unix.c
-SOURCE		os_timestamp_common.c
 SOURCE		os_timestamp_posix.c
-SOURCE		pool_policy_malloc.c
+SOURCE		pool_policy_new.cpp
 SOURCE		compat\string_compat.c
-SOURCE		sock_bsd.c
+SOURCE		sock_symbian.cpp
 SOURCE		sock_select_symbian.cpp
 SOURCE		ioqueue_symbian.cpp
+SOURCE		unicode_symbian.cpp
 
 
 SYSTEMINCLUDE	..\pjlib\include
-//SYSTEMINCLUDE	\symbian\9.1\S60_3rd_MR\epoc32\include
-//SYSTEMINCLUDE	\symbian\9.1\S60_3rd_MR\epoc32\include\libc
-SYSTEMINCLUDE	\symbian\9.1\S60_3rd\epoc32\include
-SYSTEMINCLUDE	\symbian\9.1\S60_3rd\epoc32\include\libc
+SYSTEMINCLUDE	\epoc32\include
+SYSTEMINCLUDE	\epoc32\include\libc
Index: /pjproject/branches/symbian/symbian/pjlib_test.mmp
===================================================================
--- /pjproject/branches/symbian/symbian/pjlib_test.mmp	(revision 788)
+++ /pjproject/branches/symbian/symbian/pjlib_test.mmp	(revision 788)
@@ -0,0 +1,58 @@
+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
+
+
+// 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_test.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
+//SOURCE	main.c
+
+
+SYSTEMINCLUDE	..\pjlib\include
+SYSTEMINCLUDE	\epoc32\include
+SYSTEMINCLUDE	\epoc32\include\libc
+//SYSTEMINCLUDE	\symbian\9.1\S60_3rd_MR\epoc32\include
+//SYSTEMINCLUDE	\symbian\9.1\S60_3rd_MR\epoc32\include\libc
+
+LIBRARY		pjlib.lib esock.lib insock.lib charconv.lib euser.lib estlib.lib eexe.lib
+STATICLIBRARY   ecrt0.lib
+CAPABILITY	None
+
Index: /pjproject/branches/symbian/symbian/s.bat
===================================================================
--- /pjproject/branches/symbian/symbian/s.bat	(revision 787)
+++ /pjproject/branches/symbian/symbian/s.bat	(revision 788)
@@ -1,4 +1,5 @@
 rem set MWSym2Libraries=1
-set EPOCROOT=\Symbian\9.1\S60_3rd\
+rem set EPOCROOT=\Symbian\9.1\S60_3rd\
+set EPOCROOT=\Symbian\UIQ3SDK\
 bldmake bldfiles
 call b.bat
