PageRenderTime 48ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/CSipSimple/jni/pjsip/sources/pjlib/src/pj/sock_symbian.cpp

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