blob: c40c2236fa9b57f513a5c6e0c813d411af8153f4 [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $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
39class 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//
48class CPjSocket
49{
50public:
51 enum
52 {
53 MAX_LEN = 1500,
54 };
55
56 // Construct CPjSocket
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
67 int GetAf() const
68 {
69 return af_;
70 }
71
72 // Get the internal RSocket
73 RSocket& Socket()
74 {
75 return sock_;
76 }
77
78 // Get socket connected flag.
79 bool IsConnected() const
80 {
81 return connected_;
82 }
83
84 // Set socket connected flag.
85 void SetConnected(bool connected)
86 {
87 connected_ = connected;
88 }
89
90 // Get socket type
91 int GetSockType() const
92 {
93 return sock_type_;
94 }
95
96 // Returns true if socket is a datagram
97 bool IsDatagram() const
98 {
99 return sock_type_ == KSockDatagram;
100 }
101
102 // Get socket reader, if any.
103 // May return NULL.
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
115private:
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//
129class CPjSocketReader : public CActive
130{
131public:
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.
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
167private:
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//
188class CPjTimeoutTimer : public CActive
189{
190public:
191 static CPjTimeoutTimer *NewL();
192 ~CPjTimeoutTimer();
193
194 void StartTimer(TUint miliSeconds);
195 bool HasTimedOut() const;
196
197protected:
198 virtual void RunL();
199 virtual void DoCancel();
200 virtual TInt RunError(TInt aError);
201
202private:
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//
215class PjSymbianOS
216{
217public:
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.
244 RSocketServ &SocketServ()
245 {
246 return appSocketServ_ ? *appSocketServ_ : socketServ_;
247 }
248
249 // Get RConnection instance, if any.
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
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
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 //
334 bool IsConnectionUp() const
335 {
336 return isConnectionUp_;
337 }
338
339 //
340 // Set access point connection status
341 //
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
362 CConsoleBase *Console()
363 {
364 return console_;
365 }
366
367 //
368 // Get select() timeout timer.
369 //
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
385private:
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
405private:
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