blob: be7fdb55c166e85d4340ab206d026d6820086a43 [file] [log] [blame]
Benny Prijonof260e462007-04-30 21:03:32 +00001/* $Id$ */
2/*
Benny Prijono32177c02008-06-20 22:44:47 +00003 * Copyright (C)2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijonof260e462007-04-30 21:03:32 +00004 *
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 Prijono62b86eb2007-12-01 08:52:57 +000022#include <pj/assert.h>
23#include <pj/errno.h>
Benny Prijonof260e462007-04-30 21:03:32 +000024#include <pj/sock.h>
Benny Prijono7d3e12c2007-10-26 05:25:35 +000025#include <pj/os.h>
Benny Prijonob2c96822007-05-03 13:31:21 +000026#include <pj/string.h>
Benny Prijonof260e462007-04-30 21:03:32 +000027
28#include <e32base.h>
29#include <e32cmn.h>
30#include <e32std.h>
Benny Prijono1f61a8f2007-08-16 10:11:44 +000031#include <es_sock.h>
Benny Prijonof260e462007-04-30 21:03:32 +000032#include <in_sock.h>
Benny Prijonoa2814442007-08-16 15:33:42 +000033#include <charconv.h>
Benny Prijonof260e462007-04-30 21:03:32 +000034#include <utf.h>
35#include <e32cons.h>
36
37// Forward declarations
38class CPjSocketReader;
39
Benny Prijonob2c96822007-05-03 13:31:21 +000040#ifndef PJ_SYMBIAN_TIMER_PRIORITY
41# define PJ_SYMBIAN_TIMER_PRIORITY EPriorityNormal
42#endif
43
Benny Prijonof260e462007-04-30 21:03:32 +000044//
45// PJLIB Symbian's Socket
46//
47class CPjSocket
48{
49public:
50 enum
51 {
52 MAX_LEN = 1500,
53 };
54
55 // Construct CPjSocket
Benny Prijono62b86eb2007-12-01 08:52:57 +000056 CPjSocket(int af, RSocket &sock)
57 : af_(af), sock_(sock), connected_(false), sockReader_(NULL)
Benny Prijonof260e462007-04-30 21:03:32 +000058 {
59 }
60
61 // Destroy CPjSocket
62 ~CPjSocket();
63
Benny Prijono62b86eb2007-12-01 08:52:57 +000064 // Get address family
65 int GetAf() const
66 {
67 return af_;
68 }
69
Benny Prijonof260e462007-04-30 21:03:32 +000070 // 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 Prijono897f9f82007-05-03 19:56:21 +000098 // Delete socket reader when it's not wanted.
99 void DestroyReader();
100
Benny Prijonof260e462007-04-30 21:03:32 +0000101private:
Benny Prijono62b86eb2007-12-01 08:52:57 +0000102 int af_;
Benny Prijonof260e462007-04-30 21:03:32 +0000103 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//
113class CPjSocketReader : public CActive
114{
115public:
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
151private:
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//
172class CPjTimeoutTimer : public CActive
173{
174public:
175 static CPjTimeoutTimer *NewL();
176 ~CPjTimeoutTimer();
177
178 void StartTimer(TUint miliSeconds);
179 bool HasTimedOut() const;
180
181protected:
182 virtual void RunL();
183 virtual void DoCancel();
184 virtual TInt RunError(TInt aError);
185
186private:
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//
199class PjSymbianOS
200{
201public:
202 //
Benny Prijonof260e462007-04-30 21:03:32 +0000203 // Get the singleton instance of PjSymbianOS
204 //
205 static PjSymbianOS *Instance();
206
207 //
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000208 // Set parameters
209 //
210 void SetParameters(pj_symbianos_params *params);
211
212 //
Benny Prijonof260e462007-04-30 21:03:32 +0000213 // 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 Prijono7d3e12c2007-10-26 05:25:35 +0000230 return appSocketServ_ ? *appSocketServ_ : socketServ_;
Benny Prijonof260e462007-04-30 21:03:32 +0000231 }
232
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000233 // Get RConnection instance, if any.
234 RConnection *Connection()
235 {
236 return appConnection_;
237 }
238
Benny Prijonof260e462007-04-30 21:03:32 +0000239 // Convert TInetAddr to pj_sockaddr_in
Benny Prijono62b86eb2007-12-01 08:52:57 +0000240 static inline pj_status_t Addr2pj(const TInetAddr & sym_addr,
241 pj_sockaddr &pj_addr,
Benny Prijono9db4bd62007-12-31 11:26:21 +0000242 int *addr_len,
243 pj_bool_t convert_ipv4_mapped_addr = PJ_FALSE)
Benny Prijonof260e462007-04-30 21:03:32 +0000244 {
Benny Prijono9db4bd62007-12-31 11:26:21 +0000245 TUint fam = sym_addr.Family();
Benny Prijonobc9f61c2007-12-12 14:09:14 +0000246 pj_bzero(&pj_addr, *addr_len);
Benny Prijono9db4bd62007-12-31 11:26:21 +0000247 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 Prijono80025db2007-12-02 15:36:46 +0000253 PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in), PJ_ETOOSMALL);
Benny Prijono62b86eb2007-12-01 08:52:57 +0000254 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 Prijono9db4bd62007-12-31 11:26:21 +0000257 } else if (fam == PJ_AF_INET6) {
Benny Prijono80025db2007-12-02 15:36:46 +0000258 PJ_ASSERT_RETURN(*addr_len>=(int)sizeof(pj_sockaddr_in6), PJ_ETOOSMALL);
Benny Prijono62b86eb2007-12-01 08:52:57 +0000259 const TIp6Addr & ip6 = sym_addr.Ip6Address();
Benny Prijono9db4bd62007-12-31 11:26:21 +0000260 pj_addr.addr.sa_family = PJ_AF_INET6;
Benny Prijono62b86eb2007-12-01 08:52:57 +0000261 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 Prijonof260e462007-04-30 21:03:32 +0000272 }
273
274
275 // Convert pj_sockaddr_in to TInetAddr
Benny Prijono62b86eb2007-12-01 08:52:57 +0000276 static inline pj_status_t pj2Addr(const pj_sockaddr &pj_addr,
277 int addrlen,
278 TInetAddr & sym_addr)
Benny Prijonof260e462007-04-30 21:03:32 +0000279 {
Benny Prijono62b86eb2007-12-01 08:52:57 +0000280 if (pj_addr.addr.sa_family == PJ_AF_INET) {
Benny Prijono80025db2007-12-02 15:36:46 +0000281 PJ_ASSERT_RETURN(addrlen >= (int)sizeof(pj_sockaddr_in), PJ_EINVAL);
Benny Prijono62b86eb2007-12-01 08:52:57 +0000282 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 Prijono80025db2007-12-02 15:36:46 +0000288 PJ_ASSERT_RETURN(addrlen>=(int)sizeof(pj_sockaddr_in6), PJ_EINVAL);
Benny Prijono62b86eb2007-12-01 08:52:57 +0000289 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 Prijonof260e462007-04-30 21:03:32 +0000298 }
299
300
301 //
302 // Resolver helper
303 //
304
305 // Get RHostResolver instance
Benny Prijono62b86eb2007-12-01 08:52:57 +0000306 RHostResolver & GetResolver(int af)
Benny Prijonof260e462007-04-30 21:03:32 +0000307 {
Benny Prijono62b86eb2007-12-01 08:52:57 +0000308 if (af==PJ_AF_INET6) {
309 return appHostResolver6_ ? *appHostResolver6_ : hostResolver6_;
310 } else {
311 return appHostResolver_ ? *appHostResolver_ : hostResolver_;
312 }
Benny Prijonof260e462007-04-30 21:03:32 +0000313 }
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
354private:
355 bool isSocketServInitialized_;
356 RSocketServ socketServ_;
357
358 bool isResolverInitialized_;
359 RHostResolver hostResolver_;
Benny Prijono62b86eb2007-12-01 08:52:57 +0000360 RHostResolver hostResolver6_;
Benny Prijonof260e462007-04-30 21:03:32 +0000361
362 CConsoleBase* console_;
363
364 CPjTimeoutTimer *selectTimeoutTimer_;
365
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000366 // App parameters
367 RSocketServ *appSocketServ_;
368 RConnection *appConnection_;
369 RHostResolver *appHostResolver_;
Benny Prijono62b86eb2007-12-01 08:52:57 +0000370 RHostResolver *appHostResolver6_;
Benny Prijono7d3e12c2007-10-26 05:25:35 +0000371
Benny Prijonof260e462007-04-30 21:03:32 +0000372private:
373 PjSymbianOS();
374};
375
376
377#endif /* __OS_SYMBIAN_H__ */
378