From 8f426164cc8b5ca4ea96766bf78fd2d1f28cd656 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Thu, 3 May 2007 13:31:21 +0000 Subject: Implemented ticket #246, #247, #261, #268, #250 for Symbian git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1246 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/src/pj/guid_simple.c | 4 +- pjlib/src/pj/ioqueue_symbian.cpp | 46 ++----- pjlib/src/pj/os_core_symbian.cpp | 8 +- pjlib/src/pj/os_symbian.h | 15 ++- pjlib/src/pj/sock_symbian.cpp | 31 +++-- pjlib/src/pj/timer_symbian.cpp | 272 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 317 insertions(+), 59 deletions(-) create mode 100644 pjlib/src/pj/timer_symbian.cpp (limited to 'pjlib/src/pj') diff --git a/pjlib/src/pj/guid_simple.c b/pjlib/src/pj/guid_simple.c index 05744bc9..fecdd78f 100644 --- a/pjlib/src/pj/guid_simple.c +++ b/pjlib/src/pj/guid_simple.c @@ -57,8 +57,8 @@ PJ_DEF(pj_str_t*) pj_generate_unique_string(pj_str_t *str) } strcpy(str->ptr, str_pid); - sprintf(str->ptr+4, "%04x", clock_seq++); - pj_memcpy(str->ptr+8, str_mac_addr, 12); + sprintf(str->ptr+4, "%08x", clock_seq++); + pj_memcpy(str->ptr+12, str_mac_addr, 8); str->slen = 20; return str; diff --git a/pjlib/src/pj/ioqueue_symbian.cpp b/pjlib/src/pj/ioqueue_symbian.cpp index df1fa46c..6768cc01 100644 --- a/pjlib/src/pj/ioqueue_symbian.cpp +++ b/pjlib/src/pj/ioqueue_symbian.cpp @@ -34,7 +34,6 @@ class CIoqueueCallback; struct pj_ioqueue_t { int eventCount; - CPjTimeoutTimer *timeoutTimer; }; @@ -438,8 +437,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, PJ_UNUSED_ARG(max_fd); - ioq = (pj_ioqueue_t*) pj_pool_zalloc(pool, sizeof(pj_ioqueue_t)); - ioq->timeoutTimer = CPjTimeoutTimer::NewL(); + ioq = PJ_POOL_ZALLOC_T(pool, pj_ioqueue_t); *p_ioqueue = ioq; return PJ_SUCCESS; } @@ -450,9 +448,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, */ PJ_DEF(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioq ) { - delete ioq->timeoutTimer; - ioq->timeoutTimer = NULL; - + PJ_UNUSED_ARG(ioq); return PJ_SUCCESS; } @@ -487,7 +483,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, { pj_ioqueue_key_t *key; - key = (pj_ioqueue_key_t*) pj_pool_zalloc(pool, sizeof(pj_ioqueue_key_t)); + key = PJ_POOL_ZALLOC_T(pool, pj_ioqueue_key_t); key->cbObj = CIoqueueCallback::NewL(ioq, key, sock, cb, user_data); *p_key = key; @@ -552,7 +548,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_set_user_data( pj_ioqueue_key_t *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); + pj_bzero(op_key, size); } @@ -634,34 +630,12 @@ PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key, PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioq, const pj_time_val *timeout) { - CPjTimeoutTimer *timer; - - if (timeout) { - //if (!ioq->timeoutTimer->IsActive()) - if (0) - timer = ioq->timeoutTimer; - else - timer = CPjTimeoutTimer::NewL(); - - timer->StartTimer(timeout->sec*1000 + timeout->msec); - - } else { - timer = NULL; - } - - ioq->eventCount = 0; - - do { - PjSymbianOS::Instance()->WaitForActiveObjects(); - } while (ioq->eventCount == 0 && (!timer || (timer && !timer->HasTimedOut()))); - - if (timer && !timer->HasTimedOut()) - timer->Cancel(); - - if (timer && timer != ioq->timeoutTimer) - delete timer; - - return ioq->eventCount; + /* Polling is not necessary on Symbian, since all async activities + * are registered to active scheduler. + */ + PJ_UNUSED_ARG(ioq); + PJ_UNUSED_ARG(timeout); + return 0; } diff --git a/pjlib/src/pj/os_core_symbian.cpp b/pjlib/src/pj/os_core_symbian.cpp index d0bbb157..a55b548a 100644 --- a/pjlib/src/pj/os_core_symbian.cpp +++ b/pjlib/src/pj/os_core_symbian.cpp @@ -83,7 +83,7 @@ static void (*atexit_func[32])(void); // CPjTimeoutTimer::CPjTimeoutTimer() -: CActive(EPriorityNormal), hasTimedOut_(PJ_FALSE) +: CActive(PJ_SYMBIAN_TIMER_PRIORITY), hasTimedOut_(PJ_FALSE) { } @@ -420,13 +420,7 @@ PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *rec) */ PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec) { - //Not a good idea, as we don't want network events to - //arrive while we're not polling them: - //PjSymbianOS::Instance()->WaitForActiveObjects(); - - //.. so rather use this, which won't wake up Active Objects: User::After(msec*1000); - return PJ_SUCCESS; } diff --git a/pjlib/src/pj/os_symbian.h b/pjlib/src/pj/os_symbian.h index 06973104..929070b3 100644 --- a/pjlib/src/pj/os_symbian.h +++ b/pjlib/src/pj/os_symbian.h @@ -20,6 +20,7 @@ #define __OS_SYMBIAN_H__ #include +#include #include #include @@ -33,6 +34,10 @@ // Forward declarations class CPjSocketReader; +#ifndef PJ_SYMBIAN_TIMER_PRIORITY +# define PJ_SYMBIAN_TIMER_PRIORITY EPriorityNormal +#endif + // // PJLIB Symbian's Socket // @@ -216,10 +221,10 @@ public: static inline void Addr2pj(const TInetAddr & sym_addr, pj_sockaddr_in &pj_addr) { - memset(&pj_addr, 0, sizeof(pj_sockaddr_in)); + pj_bzero(&pj_addr, 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(); + pj_addr.sin_addr.s_addr = pj_htonl(sym_addr.Address()); + pj_addr.sin_port = pj_htons((pj_uint16_t) sym_addr.Port()); } @@ -228,8 +233,8 @@ public: TInetAddr & sym_addr) { sym_addr.Init(KAfInet); - sym_addr.SetAddress((TUint32)pj_addr.sin_addr.s_addr); - sym_addr.SetPort(pj_addr.sin_port); + sym_addr.SetAddress((TUint32)pj_ntohl(pj_addr.sin_addr.s_addr)); + sym_addr.SetPort(pj_ntohs(pj_addr.sin_port)); } diff --git a/pjlib/src/pj/sock_symbian.cpp b/pjlib/src/pj/sock_symbian.cpp index 5615dde7..8d2ab077 100644 --- a/pjlib/src/pj/sock_symbian.cpp +++ b/pjlib/src/pj/sock_symbian.cpp @@ -210,8 +210,11 @@ void CPjSocketReader::ReadData(TDes8 &aDesc, TInetAddr *addr) */ PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort) { - /* There's no difference in host/network byte order in Symbian */ +#if PJ_IS_LITTLE_ENDIAN + return pj_swap16(netshort); +#else return netshort; +#endif } /* @@ -219,8 +222,11 @@ PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort) */ PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort) { - /* There's no difference in host/network byte order in Symbian */ +#if PJ_IS_LITTLE_ENDIAN + return pj_swap16(hostshort); +#else return hostshort; +#endif } /* @@ -228,8 +234,11 @@ PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort) */ PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong) { - /* There's no difference in host/network byte order in Symbian */ +#if PJ_IS_LITTLE_ENDIAN + return pj_swap32(netlong); +#else return netlong; +#endif } /* @@ -237,8 +246,11 @@ PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong) */ PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong) { - /* There's no difference in host/network byte order in Symbian */ - return hostlong; +#if PJ_IS_LITTLE_ENDIAN + return pj_swap32(hostlong); +#else + return netlong; +#endif } /* @@ -250,7 +262,8 @@ 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); + /* (Symbian IP address is in host byte order) */ + TInetAddr temp_addr((TUint32)pj_ntohl(inaddr.s_addr), (TUint)0); temp_addr.Output(str16); return pj_unicode_to_ansi(str16.PtrZ(), str16.Length(), @@ -294,8 +307,8 @@ PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp) TInetAddr addr; addr.Init(KAfInet); if (addr.Input(ip_addr) == KErrNone) { - /* Success */ - inp->s_addr = addr.Address(); + /* Success (Symbian IP address is in host byte order) */ + inp->s_addr = pj_htonl(addr.Address()); return 1; } else { /* Error */ @@ -497,7 +510,7 @@ PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sock, PJ_CHECK_STACK(); - pj_memset(&addr, 0, sizeof(addr)); + pj_bzero(&addr, sizeof(addr)); addr.sin_family = PJ_AF_INET; addr.sin_addr.s_addr = pj_htonl(addr32); addr.sin_port = pj_htons(port); diff --git a/pjlib/src/pj/timer_symbian.cpp b/pjlib/src/pj/timer_symbian.cpp new file mode 100644 index 00000000..398f7722 --- /dev/null +++ b/pjlib/src/pj/timer_symbian.cpp @@ -0,0 +1,272 @@ +/* $Id$ */ +/* + * Copyright (C)2003-2007 Benny Prijono + * + * 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 +#include +#include +#include +#include + +#include "os_symbian.h" + + +#define DEFAULT_MAX_TIMED_OUT_PER_POLL (64) + + +/** + * The implementation of timer heap. + */ +struct pj_timer_heap_t +{ + /** Maximum size of the heap. */ + pj_size_t max_size; + + /** Current size of the heap. */ + pj_size_t cur_size; + + /** Max timed out entries to process per poll. */ + unsigned max_entries_per_poll; +}; + + +////////////////////////////////////////////////////////////////////////////// +/** + * Active object for each timer entry. + */ +class CPjTimerEntry : public CActive +{ +public: + static CPjTimerEntry* NewL( pj_timer_heap_t *timer_heap, + pj_timer_entry *entry, + const pj_time_val *delay); + + ~CPjTimerEntry(); + + virtual void RunL(); + virtual void DoCancel(); + +private: + pj_timer_heap_t *timer_heap_; + pj_timer_entry *entry_; + RTimer rtimer_; + + CPjTimerEntry(pj_timer_heap_t *timer_heap, pj_timer_entry *entry); + void ConstructL(const pj_time_val *delay); +}; + + +CPjTimerEntry::CPjTimerEntry(pj_timer_heap_t *timer_heap, + pj_timer_entry *entry) +: CActive(PJ_SYMBIAN_TIMER_PRIORITY), timer_heap_(timer_heap), entry_(entry) +{ +} + +CPjTimerEntry::~CPjTimerEntry() +{ + if (IsActive()) + Cancel(); + rtimer_.Close(); +} + +void CPjTimerEntry::ConstructL(const pj_time_val *delay) +{ + rtimer_.CreateLocal(); + CActiveScheduler::Add(this); + + rtimer_.After(iStatus, PJ_TIME_VAL_MSEC(*delay) * 1000); + SetActive(); +} + +CPjTimerEntry* CPjTimerEntry::NewL(pj_timer_heap_t *timer_heap, + pj_timer_entry *entry, + const pj_time_val *delay) +{ + CPjTimerEntry *self = new CPjTimerEntry(timer_heap, entry); + CleanupStack::PushL(self); + self->ConstructL(delay); + CleanupStack::Pop(self); + + return self; +} + +void CPjTimerEntry::RunL() +{ + --timer_heap_->cur_size; + entry_->_timer_id = NULL; + entry_->cb(timer_heap_, entry_); + + // Finger's crossed! + delete this; +} + +void CPjTimerEntry::DoCancel() +{ + rtimer_.Cancel(); +} + + +////////////////////////////////////////////////////////////////////////////// + + +/* + * Calculate memory size required to create a timer heap. + */ +PJ_DEF(pj_size_t) pj_timer_heap_mem_size(pj_size_t count) +{ + return /* size of the timer heap itself: */ + sizeof(pj_timer_heap_t) + + /* size of each entry: */ + (count+2) * (sizeof(pj_timer_entry*)+sizeof(pj_timer_id_t)) + + /* lock, pool etc: */ + 132; +} + +/* + * Create a new timer heap. + */ +PJ_DEF(pj_status_t) pj_timer_heap_create( pj_pool_t *pool, + pj_size_t size, + pj_timer_heap_t **p_heap) +{ + pj_timer_heap_t *ht; + + PJ_ASSERT_RETURN(pool && p_heap, PJ_EINVAL); + + *p_heap = NULL; + + /* Allocate timer heap data structure from the pool */ + ht = PJ_POOL_ALLOC_T(pool, pj_timer_heap_t); + if (!ht) + return PJ_ENOMEM; + + /* Initialize timer heap sizes */ + ht->max_size = size; + ht->cur_size = 0; + ht->max_entries_per_poll = DEFAULT_MAX_TIMED_OUT_PER_POLL; + + *p_heap = ht; + return PJ_SUCCESS; +} + +PJ_DEF(void) pj_timer_heap_destroy( pj_timer_heap_t *ht ) +{ + PJ_UNUSED_ARG(ht); +} + +PJ_DEF(void) pj_timer_heap_set_lock( pj_timer_heap_t *ht, + pj_lock_t *lock, + pj_bool_t auto_del ) +{ + PJ_UNUSED_ARG(ht); + if (auto_del) + pj_lock_destroy(lock); +} + + +PJ_DEF(unsigned) pj_timer_heap_set_max_timed_out_per_poll(pj_timer_heap_t *ht, + unsigned count ) +{ + unsigned old_count = ht->max_entries_per_poll; + ht->max_entries_per_poll = count; + return old_count; +} + +PJ_DEF(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry, + int id, + void *user_data, + pj_timer_heap_callback *cb ) +{ + pj_assert(entry && cb); + + entry->_timer_id = NULL; + entry->id = id; + entry->user_data = user_data; + entry->cb = cb; + + return entry; +} + +PJ_DEF(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay) +{ + CPjTimerEntry *timerObj; + + PJ_ASSERT_RETURN(ht && entry && delay, PJ_EINVAL); + PJ_ASSERT_RETURN(entry->cb != NULL, PJ_EINVAL); + + /* Prevent same entry from being scheduled more than once */ + PJ_ASSERT_RETURN(entry->_timer_id == NULL, PJ_EINVALIDOP); + + timerObj = CPjTimerEntry::NewL(ht, entry, delay); + entry->_timer_id = (void*) timerObj; + + ++ht->cur_size; + return PJ_SUCCESS; +} + +PJ_DEF(int) pj_timer_heap_cancel( pj_timer_heap_t *ht, + pj_timer_entry *entry) +{ + PJ_ASSERT_RETURN(ht && entry, PJ_EINVAL); + + if (entry->_timer_id != NULL) { + CPjTimerEntry *timerObj = (CPjTimerEntry*) entry->_timer_id; + timerObj->Cancel(); + delete timerObj; + entry->_timer_id = NULL; + --ht->cur_size; + return 1; + } else { + return 0; + } +} + +PJ_DEF(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht, + pj_time_val *next_delay ) +{ + /* Polling is not necessary on Symbian, since all async activities + * are registered to active scheduler. + */ + PJ_UNUSED_ARG(ht); + if (next_delay) { + next_delay->sec = 1; + next_delay->msec = 0; + } + return 0; +} + +PJ_DEF(pj_size_t) pj_timer_heap_count( pj_timer_heap_t *ht ) +{ + PJ_ASSERT_RETURN(ht, 0); + + return ht->cur_size; +} + +PJ_DEF(pj_status_t) pj_timer_heap_earliest_time( pj_timer_heap_t * ht, + pj_time_val *timeval) +{ + /* We don't support this! */ + PJ_UNUSED_ARG(ht); + + timeval->sec = 1; + timeval->msec = 0; + + return PJ_SUCCESS; +} + -- cgit v1.2.3