Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 1 | /* $Id$ */ |
| 2 | /* |
Benny Prijono | 32177c0 | 2008-06-20 22:44:47 +0000 | [diff] [blame] | 3 | * Copyright (C)2003-2008 Benny Prijono <benny@prijono.org> |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation; either version 2 of the License, or |
| 8 | * (at your option) any later version. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 18 | */ |
| 19 | #ifndef __OS_SYMBIAN_H__ |
| 20 | #define __OS_SYMBIAN_H__ |
| 21 | |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 22 | #include <pj/assert.h> |
| 23 | #include <pj/errno.h> |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 24 | #include <pj/sock.h> |
Benny Prijono | 7d3e12c | 2007-10-26 05:25:35 +0000 | [diff] [blame] | 25 | #include <pj/os.h> |
Benny Prijono | b2c9682 | 2007-05-03 13:31:21 +0000 | [diff] [blame] | 26 | #include <pj/string.h> |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 27 | |
| 28 | #include <e32base.h> |
| 29 | #include <e32cmn.h> |
| 30 | #include <e32std.h> |
Benny Prijono | 1f61a8f | 2007-08-16 10:11:44 +0000 | [diff] [blame] | 31 | #include <es_sock.h> |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 32 | #include <in_sock.h> |
Benny Prijono | a281444 | 2007-08-16 15:33:42 +0000 | [diff] [blame] | 33 | #include <charconv.h> |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 34 | #include <utf.h> |
| 35 | #include <e32cons.h> |
| 36 | |
| 37 | // Forward declarations |
| 38 | class CPjSocketReader; |
| 39 | |
Benny Prijono | b2c9682 | 2007-05-03 13:31:21 +0000 | [diff] [blame] | 40 | #ifndef PJ_SYMBIAN_TIMER_PRIORITY |
| 41 | # define PJ_SYMBIAN_TIMER_PRIORITY EPriorityNormal |
| 42 | #endif |
| 43 | |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 44 | // |
| 45 | // PJLIB Symbian's Socket |
| 46 | // |
| 47 | class CPjSocket |
| 48 | { |
| 49 | public: |
| 50 | enum |
| 51 | { |
| 52 | MAX_LEN = 1500, |
| 53 | }; |
| 54 | |
| 55 | // Construct CPjSocket |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 56 | CPjSocket(int af, RSocket &sock) |
| 57 | : af_(af), sock_(sock), connected_(false), sockReader_(NULL) |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 58 | { |
| 59 | } |
| 60 | |
| 61 | // Destroy CPjSocket |
| 62 | ~CPjSocket(); |
| 63 | |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 64 | // Get address family |
| 65 | int GetAf() const |
| 66 | { |
| 67 | return af_; |
| 68 | } |
| 69 | |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 70 | // Get the internal RSocket |
| 71 | RSocket& Socket() |
| 72 | { |
| 73 | return sock_; |
| 74 | } |
| 75 | |
| 76 | // Get socket connected flag. |
| 77 | bool IsConnected() const |
| 78 | { |
| 79 | return connected_; |
| 80 | } |
| 81 | |
| 82 | // Set socket connected flag. |
| 83 | void SetConnected(bool connected) |
| 84 | { |
| 85 | connected_ = connected; |
| 86 | } |
| 87 | |
| 88 | // Get socket reader, if any. |
| 89 | // May return NULL. |
| 90 | CPjSocketReader *Reader() |
| 91 | { |
| 92 | return sockReader_; |
| 93 | } |
| 94 | |
| 95 | // Create socket reader. |
| 96 | CPjSocketReader *CreateReader(unsigned max_len=CPjSocket::MAX_LEN); |
| 97 | |
Benny Prijono | 897f9f8 | 2007-05-03 19:56:21 +0000 | [diff] [blame] | 98 | // Delete socket reader when it's not wanted. |
| 99 | void DestroyReader(); |
| 100 | |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 101 | private: |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 102 | int af_; |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 103 | RSocket sock_; // Must not be reference, or otherwise |
| 104 | // it may point to local variable! |
| 105 | bool connected_; |
| 106 | CPjSocketReader *sockReader_; |
| 107 | }; |
| 108 | |
| 109 | |
| 110 | // |
| 111 | // Socket reader, used by select() and ioqueue abstraction |
| 112 | // |
| 113 | class CPjSocketReader : public CActive |
| 114 | { |
| 115 | public: |
| 116 | // Construct. |
| 117 | static CPjSocketReader *NewL(CPjSocket &sock, unsigned max_len=CPjSocket::MAX_LEN); |
| 118 | |
| 119 | // Destroy; |
| 120 | ~CPjSocketReader(); |
| 121 | |
| 122 | // Start asynchronous read from the socket. |
| 123 | void StartRecv(void (*cb)(void *key)=NULL, |
| 124 | void *key=NULL, |
| 125 | TDes8 *aDesc = NULL, |
| 126 | TUint flags = 0); |
| 127 | |
| 128 | // Start asynchronous read from the socket. |
| 129 | void StartRecvFrom(void (*cb)(void *key)=NULL, |
| 130 | void *key=NULL, |
| 131 | TDes8 *aDesc = NULL, |
| 132 | TUint flags = 0, |
| 133 | TSockAddr *fromAddr = NULL); |
| 134 | |
| 135 | // Cancel asynchronous read. |
| 136 | void DoCancel(); |
| 137 | |
| 138 | // Implementation: called when read has completed. |
| 139 | void RunL(); |
| 140 | |
| 141 | // Check if there's pending data. |
| 142 | bool HasData() const |
| 143 | { |
| 144 | return buffer_.Length() != 0; |
| 145 | } |
| 146 | |
| 147 | // Append data to aDesc, up to aDesc's maximum size. |
| 148 | // If socket is datagram based, buffer_ will be clared. |
| 149 | void ReadData(TDes8 &aDesc, TInetAddr *addr=NULL); |
| 150 | |
| 151 | private: |
| 152 | CPjSocket &sock_; |
| 153 | bool isDatagram_; |
| 154 | TPtr8 buffer_; |
| 155 | TInetAddr recvAddr_; |
| 156 | |
| 157 | void (*readCb_)(void *key); |
| 158 | void *key_; |
| 159 | |
| 160 | // |
| 161 | // Constructor |
| 162 | // |
| 163 | CPjSocketReader(CPjSocket &sock); |
| 164 | void ConstructL(unsigned max_len); |
| 165 | }; |
| 166 | |
| 167 | |
| 168 | |
| 169 | // |
| 170 | // Time-out Timer Active Object |
| 171 | // |
| 172 | class CPjTimeoutTimer : public CActive |
| 173 | { |
| 174 | public: |
| 175 | static CPjTimeoutTimer *NewL(); |
| 176 | ~CPjTimeoutTimer(); |
| 177 | |
| 178 | void StartTimer(TUint miliSeconds); |
| 179 | bool HasTimedOut() const; |
| 180 | |
| 181 | protected: |
| 182 | virtual void RunL(); |
| 183 | virtual void DoCancel(); |
| 184 | virtual TInt RunError(TInt aError); |
| 185 | |
| 186 | private: |
| 187 | RTimer timer_; |
| 188 | pj_bool_t hasTimedOut_; |
| 189 | |
| 190 | CPjTimeoutTimer(); |
| 191 | void ConstructL(); |
| 192 | }; |
| 193 | |
| 194 | |
| 195 | |
| 196 | // |
| 197 | // Symbian OS helper for PJLIB |
| 198 | // |
| 199 | class PjSymbianOS |
| 200 | { |
| 201 | public: |
| 202 | // |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 203 | // Get the singleton instance of PjSymbianOS |
| 204 | // |
| 205 | static PjSymbianOS *Instance(); |
| 206 | |
| 207 | // |
Benny Prijono | 7d3e12c | 2007-10-26 05:25:35 +0000 | [diff] [blame] | 208 | // Set parameters |
| 209 | // |
| 210 | void SetParameters(pj_symbianos_params *params); |
| 211 | |
| 212 | // |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 213 | // Initialize. |
| 214 | // |
| 215 | TInt Initialize(); |
| 216 | |
| 217 | // |
| 218 | // Shutdown. |
| 219 | // |
| 220 | void Shutdown(); |
| 221 | |
| 222 | |
| 223 | // |
| 224 | // Socket helper. |
| 225 | // |
| 226 | |
| 227 | // Get RSocketServ instance to be used by all sockets. |
| 228 | RSocketServ &SocketServ() |
| 229 | { |
Benny Prijono | 7d3e12c | 2007-10-26 05:25:35 +0000 | [diff] [blame] | 230 | return appSocketServ_ ? *appSocketServ_ : socketServ_; |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 231 | } |
| 232 | |
Benny Prijono | 7d3e12c | 2007-10-26 05:25:35 +0000 | [diff] [blame] | 233 | // Get RConnection instance, if any. |
| 234 | RConnection *Connection() |
| 235 | { |
| 236 | return appConnection_; |
| 237 | } |
| 238 | |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 239 | // Convert TInetAddr to pj_sockaddr_in |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 240 | static inline pj_status_t Addr2pj(const TInetAddr & sym_addr, |
| 241 | pj_sockaddr &pj_addr, |
Benny Prijono | 9db4bd6 | 2007-12-31 11:26:21 +0000 | [diff] [blame] | 242 | int *addr_len, |
| 243 | pj_bool_t convert_ipv4_mapped_addr = PJ_FALSE) |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 244 | { |
Benny Prijono | 9db4bd6 | 2007-12-31 11:26:21 +0000 | [diff] [blame] | 245 | TUint fam = sym_addr.Family(); |
Benny Prijono | bc9f61c | 2007-12-12 14:09:14 +0000 | [diff] [blame] | 246 | pj_bzero(&pj_addr, *addr_len); |
Benny Prijono | 9db4bd6 | 2007-12-31 11:26:21 +0000 | [diff] [blame] | 247 | if (fam == PJ_AF_INET || |
| 248 | (convert_ipv4_mapped_addr && |
| 249 | fam == PJ_AF_INET6 && |
| 250 | sym_addr.IsV4Mapped())) |
| 251 | { |
| 252 | pj_addr.addr.sa_family = PJ_AF_INET; |
Benny Prijono | 80025db | 2007-12-02 15:36:46 +0000 | [diff] [blame] | 253 | PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in), PJ_ETOOSMALL); |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 254 | pj_addr.ipv4.sin_addr.s_addr = pj_htonl(sym_addr.Address()); |
| 255 | pj_addr.ipv4.sin_port = pj_htons((pj_uint16_t) sym_addr.Port()); |
| 256 | *addr_len = sizeof(pj_sockaddr_in); |
Benny Prijono | 9db4bd6 | 2007-12-31 11:26:21 +0000 | [diff] [blame] | 257 | } else if (fam == PJ_AF_INET6) { |
Benny Prijono | 80025db | 2007-12-02 15:36:46 +0000 | [diff] [blame] | 258 | PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in6), PJ_ETOOSMALL); |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 259 | const TIp6Addr & ip6 = sym_addr.Ip6Address(); |
Benny Prijono | 9db4bd6 | 2007-12-31 11:26:21 +0000 | [diff] [blame] | 260 | pj_addr.addr.sa_family = PJ_AF_INET6; |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 261 | pj_memcpy(&pj_addr.ipv6.sin6_addr, ip6.u.iAddr8, 16); |
| 262 | pj_addr.ipv6.sin6_port = pj_htons((pj_uint16_t) sym_addr.Port()); |
| 263 | pj_addr.ipv6.sin6_scope_id = pj_htonl(sym_addr.Scope()); |
| 264 | pj_addr.ipv6.sin6_flowinfo = pj_htonl(sym_addr.FlowLabel()); |
| 265 | *addr_len = sizeof(pj_sockaddr_in6); |
| 266 | } else { |
| 267 | pj_assert(!"Unsupported address family"); |
| 268 | return PJ_EAFNOTSUP; |
| 269 | } |
| 270 | |
| 271 | return PJ_SUCCESS; |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | |
| 275 | // Convert pj_sockaddr_in to TInetAddr |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 276 | static inline pj_status_t pj2Addr(const pj_sockaddr &pj_addr, |
| 277 | int addrlen, |
| 278 | TInetAddr & sym_addr) |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 279 | { |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 280 | if (pj_addr.addr.sa_family == PJ_AF_INET) { |
Benny Prijono | 80025db | 2007-12-02 15:36:46 +0000 | [diff] [blame] | 281 | PJ_ASSERT_RETURN(addrlen >= (int)sizeof(pj_sockaddr_in), PJ_EINVAL); |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 282 | sym_addr.Init(KAfInet); |
| 283 | sym_addr.SetAddress((TUint32)pj_ntohl(pj_addr.ipv4.sin_addr.s_addr)); |
| 284 | sym_addr.SetPort(pj_ntohs(pj_addr.ipv4.sin_port)); |
| 285 | } else if (pj_addr.addr.sa_family == PJ_AF_INET6) { |
| 286 | TIp6Addr ip6; |
| 287 | |
Benny Prijono | 80025db | 2007-12-02 15:36:46 +0000 | [diff] [blame] | 288 | PJ_ASSERT_RETURN(addrlen>=(int)sizeof(pj_sockaddr_in6), PJ_EINVAL); |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 289 | pj_memcpy(ip6.u.iAddr8, &pj_addr.ipv6.sin6_addr, 16); |
| 290 | sym_addr.Init(KAfInet6); |
| 291 | sym_addr.SetAddress(ip6); |
| 292 | sym_addr.SetScope(pj_ntohl(pj_addr.ipv6.sin6_scope_id)); |
| 293 | sym_addr.SetFlowLabel(pj_ntohl(pj_addr.ipv6.sin6_flowinfo)); |
| 294 | } else { |
| 295 | pj_assert(!"Unsupported address family"); |
| 296 | } |
| 297 | return PJ_SUCCESS; |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 298 | } |
| 299 | |
| 300 | |
| 301 | // |
| 302 | // Resolver helper |
| 303 | // |
| 304 | |
| 305 | // Get RHostResolver instance |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 306 | RHostResolver & GetResolver(int af) |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 307 | { |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 308 | if (af==PJ_AF_INET6) { |
| 309 | return appHostResolver6_ ? *appHostResolver6_ : hostResolver6_; |
| 310 | } else { |
| 311 | return appHostResolver_ ? *appHostResolver_ : hostResolver_; |
| 312 | } |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 313 | } |
| 314 | |
| 315 | |
| 316 | // |
| 317 | // Unicode Converter |
| 318 | // |
| 319 | |
| 320 | // Convert to Unicode |
| 321 | TInt ConvertToUnicode(TDes16 &aUnicode, const TDesC8 &aForeign); |
| 322 | |
| 323 | // Convert from Unicode |
| 324 | TInt ConvertFromUnicode(TDes8 &aForeign, const TDesC16 &aUnicode); |
| 325 | |
| 326 | // |
| 327 | // Get console |
| 328 | // |
| 329 | |
| 330 | // Get console |
| 331 | CConsoleBase *Console() |
| 332 | { |
| 333 | return console_; |
| 334 | } |
| 335 | |
| 336 | // |
| 337 | // Get select() timeout timer. |
| 338 | // |
| 339 | CPjTimeoutTimer *SelectTimeoutTimer() |
| 340 | { |
| 341 | return selectTimeoutTimer_; |
| 342 | } |
| 343 | |
| 344 | // |
| 345 | // Wait for any active objects to run. |
| 346 | // |
| 347 | void WaitForActiveObjects(TInt aPriority = CActive::EPriorityStandard) |
| 348 | { |
| 349 | TInt aError; |
| 350 | User::WaitForAnyRequest(); |
| 351 | CActiveScheduler::RunIfReady(aError, aPriority); |
| 352 | } |
| 353 | |
| 354 | private: |
| 355 | bool isSocketServInitialized_; |
| 356 | RSocketServ socketServ_; |
| 357 | |
| 358 | bool isResolverInitialized_; |
| 359 | RHostResolver hostResolver_; |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 360 | RHostResolver hostResolver6_; |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 361 | |
| 362 | CConsoleBase* console_; |
| 363 | |
| 364 | CPjTimeoutTimer *selectTimeoutTimer_; |
| 365 | |
Benny Prijono | 7d3e12c | 2007-10-26 05:25:35 +0000 | [diff] [blame] | 366 | // App parameters |
| 367 | RSocketServ *appSocketServ_; |
| 368 | RConnection *appConnection_; |
| 369 | RHostResolver *appHostResolver_; |
Benny Prijono | 62b86eb | 2007-12-01 08:52:57 +0000 | [diff] [blame] | 370 | RHostResolver *appHostResolver6_; |
Benny Prijono | 7d3e12c | 2007-10-26 05:25:35 +0000 | [diff] [blame] | 371 | |
Benny Prijono | f260e46 | 2007-04-30 21:03:32 +0000 | [diff] [blame] | 372 | private: |
| 373 | PjSymbianOS(); |
| 374 | }; |
| 375 | |
| 376 | |
| 377 | #endif /* __OS_SYMBIAN_H__ */ |
| 378 | |