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