blob: 5615dde7377b87d9e12e0c4f8ef139cb58406e87 [file] [log] [blame]
Benny Prijonof260e462007-04-30 21:03:32 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
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#include <pj/sock.h>
20#include <pj/addr_resolv.h>
21#include <pj/assert.h>
22#include <pj/errno.h>
23#include <pj/os.h>
24#include <pj/string.h>
25#include <pj/unicode.h>
26
27#include "os_symbian.h"
28
29
30/*
31 * Address families.
32 */
33const pj_uint16_t PJ_AF_UNIX = 0xFFFF;
34const pj_uint16_t PJ_AF_INET = KAfInet;
35const pj_uint16_t PJ_AF_INET6 = KAfInet6;
36const pj_uint16_t PJ_AF_PACKET = 0xFFFF;
37const pj_uint16_t PJ_AF_IRDA = 0xFFFF;
38
39/*
40 * Socket types conversion.
41 * The values here are indexed based on pj_sock_type
42 */
43const pj_uint16_t PJ_SOCK_STREAM= KSockStream;
44const pj_uint16_t PJ_SOCK_DGRAM = KSockDatagram;
45const pj_uint16_t PJ_SOCK_RAW = 0xFFFF;
46const pj_uint16_t PJ_SOCK_RDM = 0xFFFF;
47
48/* setsockop() is not really supported. */
49const pj_uint16_t PJ_SOL_SOCKET = 0xFFFF;
50const pj_uint16_t PJ_SOL_IP = 0xFFFF;
51const pj_uint16_t PJ_SOL_TCP = 0xFFFF;
52const pj_uint16_t PJ_SOL_UDP = 0xFFFF;
53const pj_uint16_t PJ_SOL_IPV6 = 0xFFFF;
54
55/* ioctl() is also not supported. */
56const pj_uint16_t PJ_SO_TYPE = 0xFFFF;
57const pj_uint16_t PJ_SO_RCVBUF = 0xFFFF;
58const pj_uint16_t PJ_SO_SNDBUF = 0xFFFF;
59
60
61/////////////////////////////////////////////////////////////////////////////
62//
63// CPjSocket implementation.
64// (declaration is in os_symbian.h)
65//
66
67CPjSocket::~CPjSocket()
68{
69 if (sockReader_) {
70 if (sockReader_->IsActive())
71 sockReader_->Cancel();
72 delete sockReader_;
73 sockReader_ = NULL;
74 }
75 sock_.Close();
76}
77
78
79// Create socket reader.
80CPjSocketReader *CPjSocket::CreateReader(unsigned max_len)
81{
82 pj_assert(sockReader_ == NULL);
83 return sockReader_ = CPjSocketReader::NewL(*this, max_len);
84}
85
86
87/////////////////////////////////////////////////////////////////////////////
88//
89// CPjSocketReader implementation
90// (declaration in os_symbian.h)
91//
92
93
94CPjSocketReader::CPjSocketReader(CPjSocket &sock)
95: CActive(EPriorityStandard),
96 sock_(sock), buffer_(NULL, 0), readCb_(NULL), key_(NULL)
97{
98}
99
100
101void CPjSocketReader::ConstructL(unsigned max_len)
102{
103 TProtocolDesc aProtocol;
104 TInt err;
105
106 err = sock_.Socket().Info(aProtocol);
107 User::LeaveIfError(err);
108
109 isDatagram_ = (aProtocol.iSockType == KSockDatagram);
110
111 TUint8 *ptr = new TUint8[max_len];
112 buffer_.Set(ptr, 0, (TInt)max_len);
113 CActiveScheduler::Add(this);
114}
115
116CPjSocketReader *CPjSocketReader::NewL(CPjSocket &sock, unsigned max_len)
117{
118 CPjSocketReader *self = new (ELeave) CPjSocketReader(sock);
119 CleanupStack::PushL(self);
120 self->ConstructL(max_len);
121 CleanupStack::Pop(self);
122
123 return self;
124}
125
126
127CPjSocketReader::~CPjSocketReader()
128{
129 const TUint8 *data = buffer_.Ptr();
130 delete [] data;
131}
132
133void CPjSocketReader::StartRecv(void (*cb)(void *key),
134 void *key,
135 TDes8 *aDesc,
136 TUint flags)
137{
138 StartRecvFrom(cb, key, aDesc, flags, NULL);
139}
140
141void CPjSocketReader::StartRecvFrom(void (*cb)(void *key),
142 void *key,
143 TDes8 *aDesc,
144 TUint flags,
145 TSockAddr *fromAddr)
146{
147 readCb_ = cb;
148 key_ = key;
149
150 if (aDesc == NULL) aDesc = &buffer_;
151 if (fromAddr == NULL) fromAddr = &recvAddr_;
152
153 sock_.Socket().RecvFrom(*aDesc, *fromAddr, flags, iStatus);
Benny Prijono5d542642007-05-02 18:54:19 +0000154 SetActive();
Benny Prijonof260e462007-04-30 21:03:32 +0000155}
156
157void CPjSocketReader::DoCancel()
158{
159 sock_.Socket().CancelRecv();
160}
161
162void CPjSocketReader::RunL()
163{
164 void (*old_cb)(void *key) = readCb_;
165 void *old_key = key_;
166 bool is_active = IsActive();
167
168 readCb_ = NULL;
169 key_ = NULL;
170
171 if (old_cb) {
172 (*old_cb)(old_key);
173 }
174}
175
176// Append data to aDesc, up to aDesc's maximum size.
177// If socket is datagram based, buffer_ will be clared.
178void CPjSocketReader::ReadData(TDes8 &aDesc, TInetAddr *addr)
179{
180 if (isDatagram_)
181 aDesc.Zero();
182
183 if (buffer_.Length() == 0)
184 return;
185
186 TInt size_to_copy = aDesc.MaxLength() - aDesc.Length();
187 if (size_to_copy > buffer_.Length())
188 size_to_copy = buffer_.Length();
189
190 aDesc.Append(buffer_.Ptr(), size_to_copy);
191
192 if (isDatagram_)
193 buffer_.Zero();
194 else
195 buffer_.Delete(0, size_to_copy);
196
197 if (addr)
198 *addr = recvAddr_;
199}
200
201
202
203/////////////////////////////////////////////////////////////////////////////
204//
205// PJLIB's sock.h implementation
206//
207
208/*
209 * Convert 16-bit value from network byte order to host byte order.
210 */
211PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
212{
213 /* There's no difference in host/network byte order in Symbian */
214 return netshort;
215}
216
217/*
218 * Convert 16-bit value from host byte order to network byte order.
219 */
220PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
221{
222 /* There's no difference in host/network byte order in Symbian */
223 return hostshort;
224}
225
226/*
227 * Convert 32-bit value from network byte order to host byte order.
228 */
229PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
230{
231 /* There's no difference in host/network byte order in Symbian */
232 return netlong;
233}
234
235/*
236 * Convert 32-bit value from host byte order to network byte order.
237 */
238PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
239{
240 /* There's no difference in host/network byte order in Symbian */
241 return hostlong;
242}
243
244/*
245 * Convert an Internet host address given in network byte order
246 * to string in standard numbers and dots notation.
247 */
248PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
249{
250 static TBuf<20> str16;
251 static char str8[20];
252
253 TInetAddr temp_addr((TUint32)inaddr.s_addr, (TUint)0);
254 temp_addr.Output(str16);
255
256 return pj_unicode_to_ansi(str16.PtrZ(), str16.Length(),
257 str8, sizeof(str8));
258}
259
260/*
261 * This function converts the Internet host address cp from the standard
262 * numbers-and-dots notation into binary data and stores it in the structure
263 * that inp points to.
264 */
265PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
266{
267 enum { MAXIPLEN = 16 };
268
269 /* Initialize output with PJ_INADDR_NONE.
270 * Some apps relies on this instead of the return value
271 * (and anyway the return value is quite confusing!)
272 */
273 inp->s_addr = PJ_INADDR_NONE;
274
275 /* Caution:
276 * this function might be called with cp->slen >= 16
277 * (i.e. when called with hostname to check if it's an IP addr).
278 */
279 PJ_ASSERT_RETURN(cp && cp->slen && inp, 0);
280 if (cp->slen >= 16) {
281 return 0;
282 }
283
284 char tempaddr8[MAXIPLEN];
285 pj_memcpy(tempaddr8, cp->ptr, cp->slen);
286 tempaddr8[cp->slen] = '\0';
287
288 wchar_t tempaddr16[MAXIPLEN];
289 pj_ansi_to_unicode(tempaddr8, pj_ansi_strlen(tempaddr8),
290 tempaddr16, sizeof(tempaddr16));
291
292 TBuf<MAXIPLEN> ip_addr(tempaddr16);
293
294 TInetAddr addr;
295 addr.Init(KAfInet);
296 if (addr.Input(ip_addr) == KErrNone) {
297 /* Success */
298 inp->s_addr = addr.Address();
299 return 1;
300 } else {
301 /* Error */
302 return 0;
303 }
304}
305
306/*
307 * Convert address string with numbers and dots to binary IP address.
308 */
309PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
310{
311 pj_in_addr addr;
312
313 pj_inet_aton(cp, &addr);
314 return addr;
315}
316
317/*
318 * Convert address string with numbers and dots to binary IP address.
319 */
320PJ_DEF(pj_in_addr) pj_inet_addr2(const char *cp)
321{
322 pj_str_t str = pj_str((char*)cp);
323 return pj_inet_addr(&str);
324}
325
326/*
327 * Set the IP address of an IP socket address from string address,
328 * with resolving the host if necessary. The string address may be in a
329 * standard numbers and dots notation or may be a hostname. If hostname
330 * is specified, then the function will resolve the host into the IP
331 * address.
332 */
333PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
334 const pj_str_t *str_addr)
335{
336 PJ_CHECK_STACK();
337
338 PJ_ASSERT_RETURN(!str_addr || str_addr->slen < PJ_MAX_HOSTNAME,
339 (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
340
341 addr->sin_family = PJ_AF_INET;
342 pj_memset(addr->sin_zero, 0, sizeof(addr->sin_zero));
343
344 if (str_addr && str_addr->slen) {
345 addr->sin_addr = pj_inet_addr(str_addr);
346 if (addr->sin_addr.s_addr == PJ_INADDR_NONE) {
347 pj_hostent he;
348 pj_status_t rc;
349
350 rc = pj_gethostbyname(str_addr, &he);
351 if (rc == 0) {
352 addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
353 } else {
354 addr->sin_addr.s_addr = PJ_INADDR_NONE;
355 return rc;
356 }
357 }
358
359 } else {
360 addr->sin_addr.s_addr = 0;
361 }
362
363 return PJ_SUCCESS;
364}
365
366/*
367 * Set the IP address and port of an IP socket address.
368 * The string address may be in a standard numbers and dots notation or
369 * may be a hostname. If hostname is specified, then the function will
370 * resolve the host into the IP address.
371 */
372PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
373 const pj_str_t *str_addr,
374 pj_uint16_t port)
375{
376 PJ_ASSERT_RETURN(addr, (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
377
378 addr->sin_family = PJ_AF_INET;
379 pj_memset(addr->sin_zero, 0, sizeof(addr->sin_zero));
380 pj_sockaddr_in_set_port(addr, port);
381 return pj_sockaddr_in_set_str_addr(addr, str_addr);
382}
383
384
385/*
386 * Get hostname.
387 */
388PJ_DEF(const pj_str_t*) pj_gethostname(void)
389{
390 static char buf[PJ_MAX_HOSTNAME];
391 static pj_str_t hostname;
392
393 PJ_CHECK_STACK();
394
395 if (hostname.ptr == NULL) {
396 RHostResolver & resv = PjSymbianOS::Instance()->GetResolver();
397 TRequestStatus reqStatus;
398 THostName tmpName;
399
400 resv.GetHostName(tmpName, reqStatus);
401 User::WaitForRequest(reqStatus);
402
403 hostname.ptr = pj_unicode_to_ansi(tmpName.Ptr(), tmpName.Length(),
404 buf, sizeof(buf));
405 hostname.slen = tmpName.Length();
406 }
407 return &hostname;
408}
409
410/*
411 * Get first IP address associated with the hostname.
412 */
413PJ_DEF(pj_in_addr) pj_gethostaddr(void)
414{
415 pj_sockaddr_in addr;
416 const pj_str_t *hostname = pj_gethostname();
417
418 pj_sockaddr_in_set_str_addr(&addr, hostname);
419 return addr.sin_addr;
420}
421
422
423/*
424 * Create new socket/endpoint for communication and returns a descriptor.
425 */
426PJ_DEF(pj_status_t) pj_sock_socket(int af,
427 int type,
428 int proto,
429 pj_sock_t *p_sock)
430{
431 TInt rc;
432
433 PJ_CHECK_STACK();
434
435 /* Sanity checks. */
436 PJ_ASSERT_RETURN(p_sock!=NULL, PJ_EINVAL);
437
438 /* Set proto if none is specified. */
439 if (proto == 0) {
440 if (type == PJ_SOCK_STREAM)
441 proto = KProtocolInetTcp;
442 else if (type == PJ_SOCK_DGRAM)
443 proto = KProtocolInetUdp;
444 }
445
446 /* Create Symbian RSocket */
447 RSocket rSock;
448 rc = rSock.Open(PjSymbianOS::Instance()->SocketServ(), af, type, proto);
449 if (rc != KErrNone)
450 return PJ_RETURN_OS_ERROR(rc);
451
452
453 /* Wrap Symbian RSocket into PJLIB's CPjSocket, and return to caller */
454 CPjSocket *pjSock = new CPjSocket(rSock);
455 *p_sock = (pj_sock_t)pjSock;
456
457 return PJ_SUCCESS;
458}
459
460
461/*
462 * Bind socket.
463 */
464PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock,
465 const pj_sockaddr_t *addr,
466 int len)
467{
468 TInt rc;
469
470 PJ_CHECK_STACK();
471
472 PJ_ASSERT_RETURN(sock != 0, PJ_EINVAL);
473 PJ_ASSERT_RETURN(addr && len == sizeof(pj_sockaddr_in), PJ_EINVAL);
474
475 // Convert PJLIB's pj_sockaddr_in into Symbian's TInetAddr
476 TInetAddr inetAddr;
477 PjSymbianOS::pj2Addr(*(pj_sockaddr_in*)addr, inetAddr);
478
479 // Get the RSocket instance
480 RSocket &rSock = ((CPjSocket*)sock)->Socket();
481
482 // Bind
483 rc = rSock.Bind(inetAddr);
484
485 return (rc==KErrNone) ? PJ_SUCCESS : PJ_RETURN_OS_ERROR(rc);
486}
487
488
489/*
490 * Bind socket.
491 */
492PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sock,
493 pj_uint32_t addr32,
494 pj_uint16_t port)
495{
496 pj_sockaddr_in addr;
497
498 PJ_CHECK_STACK();
499
500 pj_memset(&addr, 0, sizeof(addr));
501 addr.sin_family = PJ_AF_INET;
502 addr.sin_addr.s_addr = pj_htonl(addr32);
503 addr.sin_port = pj_htons(port);
504
505 return pj_sock_bind(sock, &addr, sizeof(pj_sockaddr_in));
506}
507
508
509/*
510 * Close socket.
511 */
512PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sock)
513{
514 PJ_CHECK_STACK();
515
516 PJ_ASSERT_RETURN(sock != 0, PJ_EINVAL);
517
518 CPjSocket *pjSock = (CPjSocket*)sock;
519
520 // This will close the socket.
521 delete pjSock;
522
523 return PJ_SUCCESS;
524}
525
526/*
527 * Get remote's name.
528 */
529PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sock,
530 pj_sockaddr_t *addr,
531 int *namelen)
532{
533 PJ_CHECK_STACK();
534
535 PJ_ASSERT_RETURN(sock && addr && namelen &&
536 *namelen>=sizeof(pj_sockaddr_in), PJ_EINVAL);
537
538 CPjSocket *pjSock = (CPjSocket*)sock;
539 RSocket &rSock = pjSock->Socket();
540
541 // Socket must be connected.
542 PJ_ASSERT_RETURN(pjSock->IsConnected(), PJ_EINVALIDOP);
543
544 TInetAddr inetAddr;
545 rSock.RemoteName(inetAddr);
546
547 PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr_in*)addr);
548 *namelen = sizeof(pj_sockaddr_in);
549
550 return PJ_SUCCESS;
551}
552
553/*
554 * Get socket name.
555 */
556PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sock,
557 pj_sockaddr_t *addr,
558 int *namelen)
559{
560 PJ_CHECK_STACK();
561
562 PJ_ASSERT_RETURN(sock && addr && namelen &&
563 *namelen>=sizeof(pj_sockaddr_in), PJ_EINVAL);
564
565 CPjSocket *pjSock = (CPjSocket*)sock;
566 RSocket &rSock = pjSock->Socket();
567
568 TInetAddr inetAddr;
569 rSock.LocalName(inetAddr);
570
571 PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr_in*)addr);
572 *namelen = sizeof(pj_sockaddr_in);
573
574 return PJ_SUCCESS;
575}
576
577/*
578 * Send data
579 */
580PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock,
581 const void *buf,
582 pj_ssize_t *len,
583 unsigned flags)
584{
585 PJ_CHECK_STACK();
586 PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
587
588 CPjSocket *pjSock = (CPjSocket*)sock;
589 RSocket &rSock = pjSock->Socket();
590
591 // send() should only be called to connected socket
592 PJ_ASSERT_RETURN(pjSock->IsConnected(), PJ_EINVALIDOP);
593
594 TPtrC8 data((const TUint8*)buf, (TInt)*len);
595 TRequestStatus reqStatus;
596 TSockXfrLength sentLen;
597
598 rSock.Send(data, flags, reqStatus, sentLen);
599 User::WaitForRequest(reqStatus);
600
601 if (reqStatus.Int()==KErrNone) {
602 //*len = (TInt) sentLen.Length();
603 return PJ_SUCCESS;
604 } else
605 return PJ_RETURN_OS_ERROR(reqStatus.Int());
606}
607
608
609/*
610 * Send data.
611 */
612PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock,
613 const void *buf,
614 pj_ssize_t *len,
615 unsigned flags,
616 const pj_sockaddr_t *to,
617 int tolen)
618{
619 PJ_CHECK_STACK();
620 PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
621
622 CPjSocket *pjSock = (CPjSocket*)sock;
623 RSocket &rSock = pjSock->Socket();
624
625 // Only supports AF_INET for now
626 PJ_ASSERT_RETURN(tolen==sizeof(pj_sockaddr_in) &&
627 ((pj_sockaddr*)to)->addr.sa_family == PJ_AF_INET,
628 PJ_EINVAL);
629
630 TInetAddr inetAddr;
631 PjSymbianOS::pj2Addr(*(pj_sockaddr_in*)to, inetAddr);
632
633 TPtrC8 data((const TUint8*)buf, (TInt)*len);
634 TRequestStatus reqStatus;
635 TSockXfrLength sentLen;
636
637 rSock.SendTo(data, inetAddr, flags, reqStatus, sentLen);
638 User::WaitForRequest(reqStatus);
639
640 if (reqStatus.Int()==KErrNone) {
641 //For some reason TSockXfrLength is not returning correctly!
642 //*len = (TInt) sentLen.Length();
643 return PJ_SUCCESS;
644 } else
645 return PJ_RETURN_OS_ERROR(reqStatus.Int());
646}
647
648/*
649 * Receive data.
650 */
651PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock,
652 void *buf,
653 pj_ssize_t *len,
654 unsigned flags)
655{
656 PJ_CHECK_STACK();
657
658 PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
659 PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL);
660
661 CPjSocket *pjSock = (CPjSocket*)sock;
662 RSocket &rSock = pjSock->Socket();
663
664 if (pjSock->Reader()) {
665 CPjSocketReader *reader = pjSock->Reader();
666
667 while (reader->IsActive() && !reader->HasData()) {
668 User::WaitForAnyRequest();
669 }
670
671 if (reader->HasData()) {
672 TPtr8 data((TUint8*)buf, (TInt)*len);
673 TInetAddr inetAddr;
674
675 reader->ReadData(data, &inetAddr);
676
677 *len = data.Length();
678 return PJ_SUCCESS;
679 }
680 }
681
682 TRequestStatus reqStatus;
683 TSockXfrLength recvLen;
684 TPtr8 data((TUint8*)buf, (TInt)*len, (TInt)*len);
685
686 rSock.Recv(data, flags, reqStatus, recvLen);
687 User::WaitForRequest(reqStatus);
688
689 if (reqStatus == KErrNone) {
690 //*len = (TInt)recvLen.Length();
691 *len = data.Length();
692 return PJ_SUCCESS;
693 } else {
694 *len = -1;
695 return PJ_RETURN_OS_ERROR(reqStatus.Int());
696 }
697}
698
699/*
700 * Receive data.
701 */
702PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
703 void *buf,
704 pj_ssize_t *len,
705 unsigned flags,
706 pj_sockaddr_t *from,
707 int *fromlen)
708{
709 PJ_CHECK_STACK();
710
711 PJ_ASSERT_RETURN(sock && buf && len && from && fromlen, PJ_EINVAL);
712 PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL);
713 PJ_ASSERT_RETURN(*fromlen >= sizeof(pj_sockaddr_in), PJ_EINVAL);
714
715 CPjSocket *pjSock = (CPjSocket*)sock;
716 RSocket &rSock = pjSock->Socket();
717
718 if (pjSock->Reader()) {
719 CPjSocketReader *reader = pjSock->Reader();
720
721 while (reader->IsActive() && !reader->HasData()) {
722 User::WaitForAnyRequest();
723 }
724
725 if (reader->HasData()) {
726 TPtr8 data((TUint8*)buf, (TInt)*len);
727 TInetAddr inetAddr;
728
729 reader->ReadData(data, &inetAddr);
730
731 *len = data.Length();
732
733 if (from && fromlen) {
734 PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr_in*)from);
735 *fromlen = sizeof(pj_sockaddr_in);
736 }
737 return PJ_SUCCESS;
738 }
739 }
740
741 TInetAddr inetAddr;
742 TRequestStatus reqStatus;
743 TSockXfrLength recvLen;
744 TPtr8 data((TUint8*)buf, (TInt)*len, (TInt)*len);
745
746 rSock.RecvFrom(data, inetAddr, flags, reqStatus, recvLen);
747 User::WaitForRequest(reqStatus);
748
749 if (reqStatus == KErrNone) {
750 //*len = (TInt)recvLen.Length();
751 *len = data.Length();
752 *fromlen = sizeof(pj_sockaddr_in);
753 PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr_in*)from);
754 return PJ_SUCCESS;
755 } else {
756 *len = -1;
757 *fromlen = -1;
758 return PJ_RETURN_OS_ERROR(reqStatus.Int());
759 }
760}
761
762/*
763 * Get socket option.
764 */
765PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sock,
766 pj_uint16_t level,
767 pj_uint16_t optname,
768 void *optval,
769 int *optlen)
770{
771 // Not supported for now.
772 PJ_UNUSED_ARG(sock);
773 PJ_UNUSED_ARG(level);
774 PJ_UNUSED_ARG(optname);
775 PJ_UNUSED_ARG(optval);
776 PJ_UNUSED_ARG(optlen);
777 return PJ_EINVALIDOP;
778}
779
780/*
781 * Set socket option.
782 */
783PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock,
784 pj_uint16_t level,
785 pj_uint16_t optname,
786 const void *optval,
787 int optlen)
788{
789 // Not supported for now.
790 PJ_UNUSED_ARG(sock);
791 PJ_UNUSED_ARG(level);
792 PJ_UNUSED_ARG(optname);
793 PJ_UNUSED_ARG(optval);
794 PJ_UNUSED_ARG(optlen);
795 return PJ_EINVALIDOP;
796}
797
798/*
799 * Connect socket.
800 */
801PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock,
802 const pj_sockaddr_t *addr,
803 int namelen)
804{
805 PJ_CHECK_STACK();
806
807 PJ_ASSERT_RETURN(sock && addr && namelen, PJ_EINVAL);
808 PJ_ASSERT_RETURN(((pj_sockaddr*)addr)->addr.sa_family == PJ_AF_INET,
809 PJ_EINVAL);
810
811 CPjSocket *pjSock = (CPjSocket*)sock;
812 RSocket &rSock = pjSock->Socket();
813
814 TInetAddr inetAddr;
815 TRequestStatus reqStatus;
816
817 PjSymbianOS::pj2Addr(*(pj_sockaddr_in*)addr, inetAddr);
818
819 rSock.Connect(inetAddr, reqStatus);
820 User::WaitForRequest(reqStatus);
821
822 if (reqStatus == KErrNone) {
823 pjSock->SetConnected(true);
824 return PJ_SUCCESS;
825 } else {
826 return PJ_RETURN_OS_ERROR(reqStatus.Int());
827 }
828}
829
830
831/*
832 * Shutdown socket.
833 */
834#if PJ_HAS_TCP
835PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sock,
836 int how)
837{
838 PJ_CHECK_STACK();
839
840 PJ_ASSERT_RETURN(sock, PJ_EINVAL);
841
842 CPjSocket *pjSock = (CPjSocket*)sock;
843 RSocket &rSock = pjSock->Socket();
844
845 RSocket::TShutdown aHow;
846 if (how == PJ_SD_RECEIVE)
847 aHow = RSocket::EStopInput;
848 else if (how == PJ_SHUT_WR)
849 aHow = RSocket::EStopOutput;
850 else
851 aHow = RSocket::ENormal;
852
853 TRequestStatus reqStatus;
854
855 rSock.Shutdown(aHow, reqStatus);
856 User::WaitForRequest(reqStatus);
857
858 if (reqStatus == KErrNone) {
859 return PJ_SUCCESS;
860 } else {
861 return PJ_RETURN_OS_ERROR(reqStatus.Int());
862 }
863}
864
865/*
866 * Start listening to incoming connections.
867 */
868PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sock,
869 int backlog)
870{
871 PJ_CHECK_STACK();
872
873 PJ_ASSERT_RETURN(sock && backlog, PJ_EINVAL);
874
875 CPjSocket *pjSock = (CPjSocket*)sock;
876 RSocket &rSock = pjSock->Socket();
877
878 TInt rc = rSock.Listen((TUint)backlog);
879
880 if (rc == KErrNone) {
881 return PJ_SUCCESS;
882 } else {
883 return PJ_RETURN_OS_ERROR(rc);
884 }
885}
886
887/*
888 * Accept incoming connections
889 */
890PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t serverfd,
891 pj_sock_t *newsock,
892 pj_sockaddr_t *addr,
893 int *addrlen)
894{
895 PJ_CHECK_STACK();
896
897 PJ_ASSERT_RETURN(serverfd && newsock, PJ_EINVAL);
898
899 CPjSocket *pjSock = (CPjSocket*)serverfd;
900 RSocket &rSock = pjSock->Socket();
901
902 // Create a 'blank' socket
903 RSocket newSock;
904 newSock.Open(PjSymbianOS::Instance()->SocketServ());
905
906 // Call Accept()
907 TRequestStatus reqStatus;
908
909 rSock.Accept(newSock, reqStatus);
910 User::WaitForRequest(reqStatus);
911
912 if (reqStatus != KErrNone) {
913 return PJ_RETURN_OS_ERROR(reqStatus.Int());
914 }
915
916 // Create PJ socket
917 CPjSocket *newPjSock = new CPjSocket(newSock);
918 newPjSock->SetConnected(true);
919
920 *newsock = (pj_sock_t) newPjSock;
921
922 if (addr && addrlen) {
923 return pj_sock_getpeername(*newsock, addr, addrlen);
924 }
925
926 return PJ_SUCCESS;
927}
928#endif /* PJ_HAS_TCP */
929
930