diff options
Diffstat (limited to 'pjlib/src/pj/os_symbian.h')
-rw-r--r-- | pjlib/src/pj/os_symbian.h | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/pjlib/src/pj/os_symbian.h b/pjlib/src/pj/os_symbian.h new file mode 100644 index 0000000..9b3511b --- /dev/null +++ b/pjlib/src/pj/os_symbian.h @@ -0,0 +1,422 @@ +/* $Id: os_symbian.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 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/assert.h> +#include <pj/errno.h> +#include <pj/sock.h> +#include <pj/os.h> +#include <pj/string.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; + +#ifndef PJ_SYMBIAN_TIMER_PRIORITY +# define PJ_SYMBIAN_TIMER_PRIORITY EPriorityNormal +#endif + +// +// PJLIB Symbian's Socket +// +class CPjSocket +{ +public: + enum + { + MAX_LEN = 1500, + }; + + // Construct CPjSocket + CPjSocket(int af, int sock_type, RSocket &sock) + : af_(af), sock_(sock), sock_type_(sock_type), connected_(false), + sockReader_(NULL) + { + } + + // Destroy CPjSocket + ~CPjSocket(); + + // Get address family + int GetAf() const + { + return af_; + } + + // 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 type + int GetSockType() const + { + return sock_type_; + } + + // Returns true if socket is a datagram + bool IsDatagram() const + { + return sock_type_ == KSockDatagram; + } + + // Get socket reader, if any. + // May return NULL. + CPjSocketReader *Reader() + { + return sockReader_; + } + + // Create socket reader. + CPjSocketReader *CreateReader(unsigned max_len=CPjSocket::MAX_LEN); + + // Delete socket reader when it's not wanted. + void DestroyReader(); + +private: + int af_; + RSocket sock_; // Must not be reference, or otherwise + // it may point to local variable! + unsigned sock_type_; + + bool connected_; + CPjSocketReader *sockReader_; +}; + + +// +// Socket reader, used by select() and ioqueue abstraction +// +class CPjSocketReader : public CActive +{ +public: + // Construct. + static CPjSocketReader *NewL(CPjSocket &sock, unsigned max_len=CPjSocket::MAX_LEN); + + // Destroy; + ~CPjSocketReader(); + + // Start asynchronous read from the socket. + void StartRecv(void (*cb)(void *key)=NULL, + void *key=NULL, + TDes8 *aDesc = NULL, + TUint flags = 0); + + // Start asynchronous read from the socket. + void StartRecvFrom(void (*cb)(void *key)=NULL, + void *key=NULL, + TDes8 *aDesc = NULL, + TUint flags = 0, + TSockAddr *fromAddr = NULL); + + // Cancel asynchronous read. + void DoCancel(); + + // Implementation: called when read has completed. + void RunL(); + + // Check if there's pending data. + bool HasData() const + { + return buffer_.Length() != 0; + } + + // Append data to aDesc, up to aDesc's maximum size. + // If socket is datagram based, buffer_ will be clared. + void ReadData(TDes8 &aDesc, TInetAddr *addr=NULL); + +private: + CPjSocket &sock_; + bool isDatagram_; + TPtr8 buffer_; + TInetAddr recvAddr_; + + void (*readCb_)(void *key); + void *key_; + + // + // Constructor + // + CPjSocketReader(CPjSocket &sock); + void ConstructL(unsigned max_len); +}; + + + +// +// Time-out Timer Active Object +// +class CPjTimeoutTimer : public CActive +{ +public: + static CPjTimeoutTimer *NewL(); + ~CPjTimeoutTimer(); + + void StartTimer(TUint miliSeconds); + bool HasTimedOut() const; + +protected: + virtual void RunL(); + virtual void DoCancel(); + virtual TInt RunError(TInt aError); + +private: + RTimer timer_; + pj_bool_t hasTimedOut_; + + CPjTimeoutTimer(); + void ConstructL(); +}; + + + +// +// Symbian OS helper for PJLIB +// +class PjSymbianOS +{ +public: + // + // Get the singleton instance of PjSymbianOS + // + static PjSymbianOS *Instance(); + + // + // Set parameters + // + void SetParameters(pj_symbianos_params *params); + + // + // Initialize. + // + TInt Initialize(); + + // + // Shutdown. + // + void Shutdown(); + + + // + // Socket helper. + // + + // Get RSocketServ instance to be used by all sockets. + RSocketServ &SocketServ() + { + return appSocketServ_ ? *appSocketServ_ : socketServ_; + } + + // Get RConnection instance, if any. + RConnection *Connection() + { + return appConnection_; + } + + // Convert TInetAddr to pj_sockaddr_in + static inline pj_status_t Addr2pj(const TInetAddr & sym_addr, + pj_sockaddr &pj_addr, + int *addr_len, + pj_bool_t convert_ipv4_mapped_addr = PJ_FALSE) + { + TUint fam = sym_addr.Family(); + pj_bzero(&pj_addr, *addr_len); + if (fam == PJ_AF_INET || + (convert_ipv4_mapped_addr && + fam == PJ_AF_INET6 && + sym_addr.IsV4Mapped())) + { + pj_addr.addr.sa_family = PJ_AF_INET; + PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in), PJ_ETOOSMALL); + pj_addr.ipv4.sin_addr.s_addr = pj_htonl(sym_addr.Address()); + pj_addr.ipv4.sin_port = pj_htons((pj_uint16_t) sym_addr.Port()); + *addr_len = sizeof(pj_sockaddr_in); + } else if (fam == PJ_AF_INET6) { + PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in6), PJ_ETOOSMALL); + const TIp6Addr & ip6 = sym_addr.Ip6Address(); + pj_addr.addr.sa_family = PJ_AF_INET6; + pj_memcpy(&pj_addr.ipv6.sin6_addr, ip6.u.iAddr8, 16); + pj_addr.ipv6.sin6_port = pj_htons((pj_uint16_t) sym_addr.Port()); + pj_addr.ipv6.sin6_scope_id = pj_htonl(sym_addr.Scope()); + pj_addr.ipv6.sin6_flowinfo = pj_htonl(sym_addr.FlowLabel()); + *addr_len = sizeof(pj_sockaddr_in6); + } else { + pj_assert(!"Unsupported address family"); + return PJ_EAFNOTSUP; + } + + return PJ_SUCCESS; + } + + + // Convert pj_sockaddr_in to TInetAddr + static inline pj_status_t pj2Addr(const pj_sockaddr &pj_addr, + int addrlen, + TInetAddr & sym_addr) + { + if (pj_addr.addr.sa_family == PJ_AF_INET) { + PJ_ASSERT_RETURN(addrlen >= (int)sizeof(pj_sockaddr_in), PJ_EINVAL); + sym_addr.Init(KAfInet); + sym_addr.SetAddress((TUint32)pj_ntohl(pj_addr.ipv4.sin_addr.s_addr)); + sym_addr.SetPort(pj_ntohs(pj_addr.ipv4.sin_port)); + } else if (pj_addr.addr.sa_family == PJ_AF_INET6) { + TIp6Addr ip6; + + PJ_ASSERT_RETURN(addrlen>=(int)sizeof(pj_sockaddr_in6), PJ_EINVAL); + pj_memcpy(ip6.u.iAddr8, &pj_addr.ipv6.sin6_addr, 16); + sym_addr.Init(KAfInet6); + sym_addr.SetAddress(ip6); + sym_addr.SetScope(pj_ntohl(pj_addr.ipv6.sin6_scope_id)); + sym_addr.SetFlowLabel(pj_ntohl(pj_addr.ipv6.sin6_flowinfo)); + } else { + pj_assert(!"Unsupported address family"); + } + return PJ_SUCCESS; + } + + + // + // Resolver helper + // + + // Get RHostResolver instance + RHostResolver & GetResolver(int af) + { + if (af==PJ_AF_INET6) { + return appHostResolver6_ ? *appHostResolver6_ : hostResolver6_; + } else { + return appHostResolver_ ? *appHostResolver_ : hostResolver_; + } + } + + // + // Return true if the access point connection is up + // + bool IsConnectionUp() const + { + return isConnectionUp_; + } + + // + // Set access point connection status + // + void SetConnectionStatus(bool up) + { + isConnectionUp_ = up; + } + + // + // 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::Current()->WaitForAnyRequest(); + CActiveScheduler::RunIfReady(aError, aPriority); + } + +private: + bool isConnectionUp_; + + bool isSocketServInitialized_; + RSocketServ socketServ_; + + bool isResolverInitialized_; + RHostResolver hostResolver_; + RHostResolver hostResolver6_; + + CConsoleBase* console_; + + CPjTimeoutTimer *selectTimeoutTimer_; + + // App parameters + RSocketServ *appSocketServ_; + RConnection *appConnection_; + RHostResolver *appHostResolver_; + RHostResolver *appHostResolver6_; + +private: + PjSymbianOS(); +}; + +// This macro is used to check the access point connection status and return +// failure if the AP connection is down or unusable. See the documentation +// of pj_symbianos_set_connection_status() for more info +#define PJ_SYMBIAN_CHECK_CONNECTION() \ + PJ_SYMBIAN_CHECK_CONNECTION2(PJ_ECANCELLED) + +#define PJ_SYMBIAN_CHECK_CONNECTION2(retval) \ + do { \ + if (!PjSymbianOS::Instance()->IsConnectionUp()) \ + return retval; \ + } while (0); + +#endif /* __OS_SYMBIAN_H__ */ + |