blob: 3497e7afa08181978c94c5c0af10af82ea38d203 [file] [log] [blame]
Benny Prijonof260e462007-04-30 21:03:32 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijonof260e462007-04-30 21:03:32 +00005 *
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
Benny Prijono62b86eb2007-12-01 08:52:57 +000023#include <pj/assert.h>
24#include <pj/errno.h>
Benny Prijonof260e462007-04-30 21:03:32 +000025#include <pj/sock.h>
Benny Prijono7d3e12c2007-10-26 05:25:35 +000026#include <pj/os.h>
Benny Prijonob2c96822007-05-03 13:31:21 +000027#include <pj/string.h>
Benny Prijonof260e462007-04-30 21:03:32 +000028
29#include <e32base.h>
30#include <e32cmn.h>
31#include <e32std.h>
Benny Prijono1f61a8f2007-08-16 10:11:44 +000032#include <es_sock.h>
Benny Prijonof260e462007-04-30 21:03:32 +000033#include <in_sock.h>
Benny Prijonoa2814442007-08-16 15:33:42 +000034#include <charconv.h>
Benny Prijonof260e462007-04-30 21:03:32 +000035#include <utf.h>
36#include <e32cons.h>
37
38// Forward declarations
39class CPjSocketReader;
40
Benny Prijonob2c96822007-05-03 13:31:21 +000041#ifndef PJ_SYMBIAN_TIMER_PRIORITY
42# define PJ_SYMBIAN_TIMER_PRIORITY EPriorityNormal
43#endif
44
Benny Prijonof260e462007-04-30 21:03:32 +000045//
46// PJLIB Symbian's Socket
47//
48class CPjSocket
49{
50public:
51 enum
52 {
53 MAX_LEN = 1500,
54 };
55
56 // Construct CPjSocket
Benny Prijono62b86eb2007-12-01 08:52:57 +000057 CPjSocket(int af, RSocket &sock)
58 : af_(af), sock_(sock), connected_(false), sockReader_(NULL)
Benny Prijonof260e462007-04-30 21:03:32 +000059 {
60 }
61
62 // Destroy CPjSocket
63 ~CPjSocket();
64
Benny Prijono62b86eb2007-12-01 08:52:57 +000065 // Get address family
66 int GetAf() const
67 {
68 return af_;
69 }
70
Benny Prijonof260e462007-04-30 21:03:32 +000071 // Get the internal RSocket
72 RSocket& Socket()
73 {
74 return sock_;
75 }
76
77 // Get socket connected flag.
78 bool IsConnected() const
79 {
80 return connected_;
81 }
82
83 // Set socket connected flag.
84 void SetConnected(bool connected)
85 {
86 connected_ = connected;
87 }
88
89 // Get socket reader, if any.
90 // May return NULL.
91 CPjSocketReader *Reader()
92 {
93 return sockReader_;
94 }
95
96 // Create socket reader.
97 CPjSocketReader *CreateReader(unsigned max_len=CPjSocket::MAX_LEN);
98
Benny Prijono897f9f82007-05-03 19:56:21 +000099 // Delete socket reader when it's not wanted.
100 void DestroyReader();
101
Benny Prijonof260e462007-04-30 21:03:32 +0000102private:
Benny Prijono62b86eb2007-12-01 08:52:57 +0000103 int af_;
Benny Prijonof260e462007-04-30 21:03:32 +0000104 RSocket sock_; // Must not be reference, or otherwise
105 // it may point to local variable!
106 bool connected_;
107 CPjSocketReader *sockReader_;
108};
109
110
111//
112// Socket reader, used by select() and ioqueue abstraction
113//
114class CPjSocketReader : public CActive
115{
116public:
117 // Construct.
118 static CPjSocketReader *NewL(CPjSocket &sock, unsigned max_len=CPjSocket::MAX_LEN);
119
120 // Destroy;
121 ~CPjSocketReader();
122
123 // Start asynchronous read from the socket.
124 void StartRecv(void (*cb)(void *key)=NULL,
125 void *key=NULL,
126 TDes8 *aDesc = NULL,
127 TUint flags = 0);
128
129 // Start asynchronous read from the socket.
130 void StartRecvFrom(void (*cb)(void *key)=NULL,
131 void *key=NULL,
132 TDes8 *aDesc = NULL,
133 TUint flags = 0,
134 TSockAddr *fromAddr = NULL);
135
136 // Cancel asynchronous read.
137 void DoCancel();
138
139 // Implementation: called when read has completed.
140 void RunL();
141
142 // Check if there's pending data.
143 bool HasData() const
144 {
145 return buffer_.Length() != 0;
146 }
147
148 // Append data to aDesc, up to aDesc's maximum size.
149 // If socket is datagram based, buffer_ will be clared.
150 void ReadData(TDes8 &aDesc, TInetAddr *addr=NULL);
151
152private:
153 CPjSocket &sock_;
154 bool isDatagram_;
155 TPtr8 buffer_;
156 TInetAddr recvAddr_;
157
158 void (*readCb_)(void *key);
159 void *key_;
160
161 //
162 // Constructor
163 //
164 CPjSocketReader(CPjSocket &sock);
165 void ConstructL(unsigned max_len);
166};
167
168
169
170//
171// Time-out Timer Active Object
172//
173class CPjTimeoutTimer : public CActive
174{
175public:
176 static CPjTimeoutTimer *NewL();
177 ~CPjTimeoutTimer();
178
179 void StartTimer(TUint miliSeconds);
180 bool HasTimedOut() const;
181
182protected:
183 virtual void RunL();
184 virtual void DoCancel();
185 virtual TInt RunError(TInt aError);
186
187private:
188 RTimer timer_;
189 pj_bool_t hasTimedOut_;
190
191 CPjTimeoutTimer();
192 void ConstructL();
193};
194
195
196
197//
198// Symbian OS helper for PJLIB
199//
200class PjSymbianOS
201{
202public:
203 //
Benny Prijonof260e462007-04-30 21:03:32 +0000204 // Get the singleton instance of PjSymbianOS
205 //
206 static PjSymbianOS *Instance();
207
208 //
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000209 // Set parameters
210 //
211 void SetParameters(pj_symbianos_params *params);
212
213 //
Benny Prijonof260e462007-04-30 21:03:32 +0000214 // Initialize.
215 //
216 TInt Initialize();
217
218 //
219 // Shutdown.
220 //
221 void Shutdown();
222
223
224 //
225 // Socket helper.
226 //
227
228 // Get RSocketServ instance to be used by all sockets.
229 RSocketServ &SocketServ()
230 {
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000231 return appSocketServ_ ? *appSocketServ_ : socketServ_;
Benny Prijonof260e462007-04-30 21:03:32 +0000232 }
233
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000234 // Get RConnection instance, if any.
235 RConnection *Connection()
236 {
237 return appConnection_;
238 }
239
Benny Prijonof260e462007-04-30 21:03:32 +0000240 // Convert TInetAddr to pj_sockaddr_in
Benny Prijono62b86eb2007-12-01 08:52:57 +0000241 static inline pj_status_t Addr2pj(const TInetAddr & sym_addr,
242 pj_sockaddr &pj_addr,
Benny Prijono9db4bd62007-12-31 11:26:21 +0000243 int *addr_len,
244 pj_bool_t convert_ipv4_mapped_addr = PJ_FALSE)
Benny Prijonof260e462007-04-30 21:03:32 +0000245 {
Benny Prijono9db4bd62007-12-31 11:26:21 +0000246 TUint fam = sym_addr.Family();
Benny Prijonobc9f61c2007-12-12 14:09:14 +0000247 pj_bzero(&pj_addr, *addr_len);
Benny Prijono9db4bd62007-12-31 11:26:21 +0000248 if (fam == PJ_AF_INET ||
249 (convert_ipv4_mapped_addr &&
250 fam == PJ_AF_INET6 &&
251 sym_addr.IsV4Mapped()))
252 {
253 pj_addr.addr.sa_family = PJ_AF_INET;
Benny Prijono80025db2007-12-02 15:36:46 +0000254 PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in), PJ_ETOOSMALL);
Benny Prijono62b86eb2007-12-01 08:52:57 +0000255 pj_addr.ipv4.sin_addr.s_addr = pj_htonl(sym_addr.Address());
256 pj_addr.ipv4.sin_port = pj_htons((pj_uint16_t) sym_addr.Port());
257 *addr_len = sizeof(pj_sockaddr_in);
Benny Prijono9db4bd62007-12-31 11:26:21 +0000258 } else if (fam == PJ_AF_INET6) {
Benny Prijono80025db2007-12-02 15:36:46 +0000259 PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in6), PJ_ETOOSMALL);
Benny Prijono62b86eb2007-12-01 08:52:57 +0000260 const TIp6Addr & ip6 = sym_addr.Ip6Address();
Benny Prijono9db4bd62007-12-31 11:26:21 +0000261 pj_addr.addr.sa_family = PJ_AF_INET6;
Benny Prijono62b86eb2007-12-01 08:52:57 +0000262 pj_memcpy(&pj_addr.ipv6.sin6_addr, ip6.u.iAddr8, 16);
263 pj_addr.ipv6.sin6_port = pj_htons((pj_uint16_t) sym_addr.Port());
264 pj_addr.ipv6.sin6_scope_id = pj_htonl(sym_addr.Scope());
265 pj_addr.ipv6.sin6_flowinfo = pj_htonl(sym_addr.FlowLabel());
266 *addr_len = sizeof(pj_sockaddr_in6);
267 } else {
268 pj_assert(!"Unsupported address family");
269 return PJ_EAFNOTSUP;
270 }
271
272 return PJ_SUCCESS;
Benny Prijonof260e462007-04-30 21:03:32 +0000273 }
274
275
276 // Convert pj_sockaddr_in to TInetAddr
Benny Prijono62b86eb2007-12-01 08:52:57 +0000277 static inline pj_status_t pj2Addr(const pj_sockaddr &pj_addr,
278 int addrlen,
279 TInetAddr & sym_addr)
Benny Prijonof260e462007-04-30 21:03:32 +0000280 {
Benny Prijono62b86eb2007-12-01 08:52:57 +0000281 if (pj_addr.addr.sa_family == PJ_AF_INET) {
Benny Prijono80025db2007-12-02 15:36:46 +0000282 PJ_ASSERT_RETURN(addrlen >= (int)sizeof(pj_sockaddr_in), PJ_EINVAL);
Benny Prijono62b86eb2007-12-01 08:52:57 +0000283 sym_addr.Init(KAfInet);
284 sym_addr.SetAddress((TUint32)pj_ntohl(pj_addr.ipv4.sin_addr.s_addr));
285 sym_addr.SetPort(pj_ntohs(pj_addr.ipv4.sin_port));
286 } else if (pj_addr.addr.sa_family == PJ_AF_INET6) {
287 TIp6Addr ip6;
288
Benny Prijono80025db2007-12-02 15:36:46 +0000289 PJ_ASSERT_RETURN(addrlen>=(int)sizeof(pj_sockaddr_in6), PJ_EINVAL);
Benny Prijono62b86eb2007-12-01 08:52:57 +0000290 pj_memcpy(ip6.u.iAddr8, &pj_addr.ipv6.sin6_addr, 16);
291 sym_addr.Init(KAfInet6);
292 sym_addr.SetAddress(ip6);
293 sym_addr.SetScope(pj_ntohl(pj_addr.ipv6.sin6_scope_id));
294 sym_addr.SetFlowLabel(pj_ntohl(pj_addr.ipv6.sin6_flowinfo));
295 } else {
296 pj_assert(!"Unsupported address family");
297 }
298 return PJ_SUCCESS;
Benny Prijonof260e462007-04-30 21:03:32 +0000299 }
300
301
302 //
303 // Resolver helper
304 //
305
306 // Get RHostResolver instance
Benny Prijono62b86eb2007-12-01 08:52:57 +0000307 RHostResolver & GetResolver(int af)
Benny Prijonof260e462007-04-30 21:03:32 +0000308 {
Benny Prijono62b86eb2007-12-01 08:52:57 +0000309 if (af==PJ_AF_INET6) {
310 return appHostResolver6_ ? *appHostResolver6_ : hostResolver6_;
311 } else {
312 return appHostResolver_ ? *appHostResolver_ : hostResolver_;
313 }
Benny Prijonof260e462007-04-30 21:03:32 +0000314 }
315
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000316 //
317 // Return true if the access point connection is up
318 //
319 bool IsConnectionUp() const
320 {
321 return isConnectionUp_;
322 }
323
324 //
325 // Set access point connection status
326 //
327 void SetConnectionStatus(bool up)
328 {
329 isConnectionUp_ = up;
330 }
Benny Prijonof260e462007-04-30 21:03:32 +0000331
332 //
333 // Unicode Converter
334 //
335
336 // Convert to Unicode
337 TInt ConvertToUnicode(TDes16 &aUnicode, const TDesC8 &aForeign);
338
339 // Convert from Unicode
340 TInt ConvertFromUnicode(TDes8 &aForeign, const TDesC16 &aUnicode);
341
342 //
343 // Get console
344 //
345
346 // Get console
347 CConsoleBase *Console()
348 {
349 return console_;
350 }
351
352 //
353 // Get select() timeout timer.
354 //
355 CPjTimeoutTimer *SelectTimeoutTimer()
356 {
357 return selectTimeoutTimer_;
358 }
359
360 //
361 // Wait for any active objects to run.
362 //
363 void WaitForActiveObjects(TInt aPriority = CActive::EPriorityStandard)
364 {
365 TInt aError;
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000366 CActiveScheduler::Current()->WaitForAnyRequest();
Benny Prijonof260e462007-04-30 21:03:32 +0000367 CActiveScheduler::RunIfReady(aError, aPriority);
368 }
369
370private:
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000371 bool isConnectionUp_;
372
Benny Prijonof260e462007-04-30 21:03:32 +0000373 bool isSocketServInitialized_;
374 RSocketServ socketServ_;
375
376 bool isResolverInitialized_;
377 RHostResolver hostResolver_;
Benny Prijono62b86eb2007-12-01 08:52:57 +0000378 RHostResolver hostResolver6_;
Benny Prijonof260e462007-04-30 21:03:32 +0000379
380 CConsoleBase* console_;
381
382 CPjTimeoutTimer *selectTimeoutTimer_;
383
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000384 // App parameters
385 RSocketServ *appSocketServ_;
386 RConnection *appConnection_;
387 RHostResolver *appHostResolver_;
Benny Prijono62b86eb2007-12-01 08:52:57 +0000388 RHostResolver *appHostResolver6_;
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000389
Benny Prijonof260e462007-04-30 21:03:32 +0000390private:
391 PjSymbianOS();
392};
393
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000394// This macro is used to check the access point connection status and return
395// failure if the AP connection is down or unusable. See the documentation
396// of pj_symbianos_set_connection_status() for more info
397#define PJ_SYMBIAN_CHECK_CONNECTION() \
398 PJ_SYMBIAN_CHECK_CONNECTION2(PJ_ECANCELLED)
399
400#define PJ_SYMBIAN_CHECK_CONNECTION2(retval) \
401 do { \
402 if (!PjSymbianOS::Instance()->IsConnectionUp()) \
403 return retval; \
404 } while (0);
Benny Prijonof260e462007-04-30 21:03:32 +0000405
406#endif /* __OS_SYMBIAN_H__ */
407