PageRenderTime 25ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/CSipSimple/jni/pjsip/sources/pjlib/src/pj/sock_bsd.c

https://bitbucket.org/bohlooli/csipsimple2
C | 849 lines | 577 code | 113 blank | 159 comment | 122 complexity | 052cf1b59d09e6f3de3fb8cc09e4905e MD5 | raw file
  1. /* $Id: sock_bsd.c 4233 2012-08-21 11:16:06Z ming $ */
  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/os.h>
  22. #include <pj/assert.h>
  23. #include <pj/string.h>
  24. #include <pj/compat/socket.h>
  25. #include <pj/addr_resolv.h>
  26. #include <pj/errno.h>
  27. #include <pj/unicode.h>
  28. /*
  29. * Address families conversion.
  30. * The values here are indexed based on pj_addr_family.
  31. */
  32. const pj_uint16_t PJ_AF_UNSPEC = AF_UNSPEC;
  33. const pj_uint16_t PJ_AF_UNIX = AF_UNIX;
  34. const pj_uint16_t PJ_AF_INET = AF_INET;
  35. const pj_uint16_t PJ_AF_INET6 = AF_INET6;
  36. #ifdef AF_PACKET
  37. const pj_uint16_t PJ_AF_PACKET = AF_PACKET;
  38. #else
  39. const pj_uint16_t PJ_AF_PACKET = 0xFFFF;
  40. #endif
  41. #ifdef AF_IRDA
  42. const pj_uint16_t PJ_AF_IRDA = AF_IRDA;
  43. #else
  44. const pj_uint16_t PJ_AF_IRDA = 0xFFFF;
  45. #endif
  46. /*
  47. * Socket types conversion.
  48. * The values here are indexed based on pj_sock_type
  49. */
  50. const pj_uint16_t PJ_SOCK_STREAM= SOCK_STREAM;
  51. const pj_uint16_t PJ_SOCK_DGRAM = SOCK_DGRAM;
  52. const pj_uint16_t PJ_SOCK_RAW = SOCK_RAW;
  53. const pj_uint16_t PJ_SOCK_RDM = SOCK_RDM;
  54. /*
  55. * Socket level values.
  56. */
  57. const pj_uint16_t PJ_SOL_SOCKET = SOL_SOCKET;
  58. #ifdef SOL_IP
  59. const pj_uint16_t PJ_SOL_IP = SOL_IP;
  60. #elif defined(PJ_WIN32) && PJ_WIN32
  61. const pj_uint16_t PJ_SOL_IP = IPPROTO_IP;
  62. #else
  63. const pj_uint16_t PJ_SOL_IP = 0;
  64. #endif /* SOL_IP */
  65. #if defined(SOL_TCP)
  66. const pj_uint16_t PJ_SOL_TCP = SOL_TCP;
  67. #elif defined(IPPROTO_TCP)
  68. const pj_uint16_t PJ_SOL_TCP = IPPROTO_TCP;
  69. #elif defined(PJ_WIN32) && PJ_WIN32
  70. const pj_uint16_t PJ_SOL_TCP = IPPROTO_TCP;
  71. #else
  72. const pj_uint16_t PJ_SOL_TCP = 6;
  73. #endif /* SOL_TCP */
  74. #ifdef SOL_UDP
  75. const pj_uint16_t PJ_SOL_UDP = SOL_UDP;
  76. #elif defined(IPPROTO_UDP)
  77. const pj_uint16_t PJ_SOL_UDP = IPPROTO_UDP;
  78. #elif defined(PJ_WIN32) && PJ_WIN32
  79. const pj_uint16_t PJ_SOL_UDP = IPPROTO_UDP;
  80. #else
  81. const pj_uint16_t PJ_SOL_UDP = 17;
  82. #endif /* SOL_UDP */
  83. #ifdef SOL_IPV6
  84. const pj_uint16_t PJ_SOL_IPV6 = SOL_IPV6;
  85. #elif defined(PJ_WIN32) && PJ_WIN32
  86. # if defined(IPPROTO_IPV6) || (_WIN32_WINNT >= 0x0501)
  87. const pj_uint16_t PJ_SOL_IPV6 = IPPROTO_IPV6;
  88. # else
  89. const pj_uint16_t PJ_SOL_IPV6 = 41;
  90. # endif
  91. #else
  92. const pj_uint16_t PJ_SOL_IPV6 = 41;
  93. #endif /* SOL_IPV6 */
  94. /* IP_TOS */
  95. #ifdef IP_TOS
  96. const pj_uint16_t PJ_IP_TOS = IP_TOS;
  97. #else
  98. const pj_uint16_t PJ_IP_TOS = 1;
  99. #endif
  100. /* TOS settings (declared in netinet/ip.h) */
  101. #ifdef IPTOS_LOWDELAY
  102. const pj_uint16_t PJ_IPTOS_LOWDELAY = IPTOS_LOWDELAY;
  103. #else
  104. const pj_uint16_t PJ_IPTOS_LOWDELAY = 0x10;
  105. #endif
  106. #ifdef IPTOS_THROUGHPUT
  107. const pj_uint16_t PJ_IPTOS_THROUGHPUT = IPTOS_THROUGHPUT;
  108. #else
  109. const pj_uint16_t PJ_IPTOS_THROUGHPUT = 0x08;
  110. #endif
  111. #ifdef IPTOS_RELIABILITY
  112. const pj_uint16_t PJ_IPTOS_RELIABILITY = IPTOS_RELIABILITY;
  113. #else
  114. const pj_uint16_t PJ_IPTOS_RELIABILITY = 0x04;
  115. #endif
  116. #ifdef IPTOS_MINCOST
  117. const pj_uint16_t PJ_IPTOS_MINCOST = IPTOS_MINCOST;
  118. #else
  119. const pj_uint16_t PJ_IPTOS_MINCOST = 0x02;
  120. #endif
  121. /* optname values. */
  122. const pj_uint16_t PJ_SO_TYPE = SO_TYPE;
  123. const pj_uint16_t PJ_SO_RCVBUF = SO_RCVBUF;
  124. const pj_uint16_t PJ_SO_SNDBUF = SO_SNDBUF;
  125. const pj_uint16_t PJ_TCP_NODELAY= TCP_NODELAY;
  126. const pj_uint16_t PJ_SO_REUSEADDR= SO_REUSEADDR;
  127. #ifdef SO_NOSIGPIPE
  128. const pj_uint16_t PJ_SO_NOSIGPIPE = SO_NOSIGPIPE;
  129. #else
  130. const pj_uint16_t PJ_SO_NOSIGPIPE = 0xFFFF;
  131. #endif
  132. #if defined(SO_PRIORITY)
  133. const pj_uint16_t PJ_SO_PRIORITY = SO_PRIORITY;
  134. #else
  135. /* This is from Linux, YMMV */
  136. const pj_uint16_t PJ_SO_PRIORITY = 12;
  137. #endif
  138. /* Multicasting is not supported e.g. in PocketPC 2003 SDK */
  139. #ifdef IP_MULTICAST_IF
  140. const pj_uint16_t PJ_IP_MULTICAST_IF = IP_MULTICAST_IF;
  141. const pj_uint16_t PJ_IP_MULTICAST_TTL = IP_MULTICAST_TTL;
  142. const pj_uint16_t PJ_IP_MULTICAST_LOOP = IP_MULTICAST_LOOP;
  143. const pj_uint16_t PJ_IP_ADD_MEMBERSHIP = IP_ADD_MEMBERSHIP;
  144. const pj_uint16_t PJ_IP_DROP_MEMBERSHIP = IP_DROP_MEMBERSHIP;
  145. #else
  146. const pj_uint16_t PJ_IP_MULTICAST_IF = 0xFFFF;
  147. const pj_uint16_t PJ_IP_MULTICAST_TTL = 0xFFFF;
  148. const pj_uint16_t PJ_IP_MULTICAST_LOOP = 0xFFFF;
  149. const pj_uint16_t PJ_IP_ADD_MEMBERSHIP = 0xFFFF;
  150. const pj_uint16_t PJ_IP_DROP_MEMBERSHIP = 0xFFFF;
  151. #endif
  152. /* recv() and send() flags */
  153. const int PJ_MSG_OOB = MSG_OOB;
  154. const int PJ_MSG_PEEK = MSG_PEEK;
  155. const int PJ_MSG_DONTROUTE = MSG_DONTROUTE;
  156. #if 0
  157. static void CHECK_ADDR_LEN(const pj_sockaddr *addr, int len)
  158. {
  159. pj_sockaddr *a = (pj_sockaddr*)addr;
  160. pj_assert((a->addr.sa_family==PJ_AF_INET && len==sizeof(pj_sockaddr_in)) ||
  161. (a->addr.sa_family==PJ_AF_INET6 && len==sizeof(pj_sockaddr_in6)));
  162. }
  163. #else
  164. #define CHECK_ADDR_LEN(addr,len)
  165. #endif
  166. /*
  167. * Convert 16-bit value from network byte order to host byte order.
  168. */
  169. PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
  170. {
  171. return ntohs(netshort);
  172. }
  173. /*
  174. * Convert 16-bit value from host byte order to network byte order.
  175. */
  176. PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
  177. {
  178. return htons(hostshort);
  179. }
  180. /*
  181. * Convert 32-bit value from network byte order to host byte order.
  182. */
  183. PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
  184. {
  185. return ntohl(netlong);
  186. }
  187. /*
  188. * Convert 32-bit value from host byte order to network byte order.
  189. */
  190. PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
  191. {
  192. return htonl(hostlong);
  193. }
  194. /*
  195. * Convert an Internet host address given in network byte order
  196. * to string in standard numbers and dots notation.
  197. */
  198. PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
  199. {
  200. #if !defined(PJ_LINUX) && !defined(PJ_LINUX_KERNEL)
  201. return inet_ntoa(*(struct in_addr*)&inaddr);
  202. #else
  203. struct in_addr addr;
  204. addr.s_addr = inaddr.s_addr;
  205. return inet_ntoa(addr);
  206. #endif
  207. }
  208. /*
  209. * This function converts the Internet host address cp from the standard
  210. * numbers-and-dots notation into binary data and stores it in the structure
  211. * that inp points to.
  212. */
  213. PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
  214. {
  215. char tempaddr[PJ_INET_ADDRSTRLEN];
  216. /* Initialize output with PJ_INADDR_NONE.
  217. * Some apps relies on this instead of the return value
  218. * (and anyway the return value is quite confusing!)
  219. */
  220. inp->s_addr = PJ_INADDR_NONE;
  221. /* Caution:
  222. * this function might be called with cp->slen >= 16
  223. * (i.e. when called with hostname to check if it's an IP addr).
  224. */
  225. PJ_ASSERT_RETURN(cp && cp->slen && inp, 0);
  226. if (cp->slen >= PJ_INET_ADDRSTRLEN) {
  227. return 0;
  228. }
  229. pj_memcpy(tempaddr, cp->ptr, cp->slen);
  230. tempaddr[cp->slen] = '\0';
  231. #if defined(PJ_SOCK_HAS_INET_ATON) && PJ_SOCK_HAS_INET_ATON != 0
  232. return inet_aton(tempaddr, (struct in_addr*)inp);
  233. #else
  234. inp->s_addr = inet_addr(tempaddr);
  235. return inp->s_addr == PJ_INADDR_NONE ? 0 : 1;
  236. #endif
  237. }
  238. /*
  239. * Convert text to IPv4/IPv6 address.
  240. */
  241. PJ_DEF(pj_status_t) pj_inet_pton(int af, const pj_str_t *src, void *dst)
  242. {
  243. char tempaddr[PJ_INET6_ADDRSTRLEN];
  244. PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EAFNOTSUP);
  245. PJ_ASSERT_RETURN(src && src->slen && dst, PJ_EINVAL);
  246. /* Initialize output with PJ_IN_ADDR_NONE for IPv4 (to be
  247. * compatible with pj_inet_aton()
  248. */
  249. if (af==PJ_AF_INET) {
  250. ((pj_in_addr*)dst)->s_addr = PJ_INADDR_NONE;
  251. }
  252. /* Caution:
  253. * this function might be called with cp->slen >= 46
  254. * (i.e. when called with hostname to check if it's an IP addr).
  255. */
  256. if (src->slen >= PJ_INET6_ADDRSTRLEN) {
  257. return PJ_ENAMETOOLONG;
  258. }
  259. pj_memcpy(tempaddr, src->ptr, src->slen);
  260. tempaddr[src->slen] = '\0';
  261. #if defined(PJ_SOCK_HAS_INET_PTON) && PJ_SOCK_HAS_INET_PTON != 0
  262. /*
  263. * Implementation using inet_pton()
  264. */
  265. if (inet_pton(af, tempaddr, dst) != 1) {
  266. pj_status_t status = pj_get_netos_error();
  267. if (status == PJ_SUCCESS)
  268. status = PJ_EUNKNOWN;
  269. return status;
  270. }
  271. return PJ_SUCCESS;
  272. #elif defined(PJ_WIN32) || defined(PJ_WIN32_WINCE)
  273. /*
  274. * Implementation on Windows, using WSAStringToAddress().
  275. * Should also work on Unicode systems.
  276. */
  277. {
  278. PJ_DECL_UNICODE_TEMP_BUF(wtempaddr,PJ_INET6_ADDRSTRLEN)
  279. pj_sockaddr sock_addr;
  280. int addr_len = sizeof(sock_addr);
  281. int rc;
  282. sock_addr.addr.sa_family = (pj_uint16_t)af;
  283. rc = WSAStringToAddress(
  284. PJ_STRING_TO_NATIVE(tempaddr,wtempaddr,sizeof(wtempaddr)),
  285. af, NULL, (LPSOCKADDR)&sock_addr, &addr_len);
  286. if (rc != 0) {
  287. /* If you get rc 130022 Invalid argument (WSAEINVAL) with IPv6,
  288. * check that you have IPv6 enabled (install it in the network
  289. * adapter).
  290. */
  291. pj_status_t status = pj_get_netos_error();
  292. if (status == PJ_SUCCESS)
  293. status = PJ_EUNKNOWN;
  294. return status;
  295. }
  296. if (sock_addr.addr.sa_family == PJ_AF_INET) {
  297. pj_memcpy(dst, &sock_addr.ipv4.sin_addr, 4);
  298. return PJ_SUCCESS;
  299. } else if (sock_addr.addr.sa_family == PJ_AF_INET6) {
  300. pj_memcpy(dst, &sock_addr.ipv6.sin6_addr, 16);
  301. return PJ_SUCCESS;
  302. } else {
  303. pj_assert(!"Shouldn't happen");
  304. return PJ_EBUG;
  305. }
  306. }
  307. #elif !defined(PJ_HAS_IPV6) || PJ_HAS_IPV6==0
  308. /* IPv6 support is disabled, just return error without raising assertion */
  309. return PJ_EIPV6NOTSUP;
  310. #else
  311. pj_assert(!"Not supported");
  312. return PJ_EIPV6NOTSUP;
  313. #endif
  314. }
  315. /*
  316. * Convert IPv4/IPv6 address to text.
  317. */
  318. PJ_DEF(pj_status_t) pj_inet_ntop(int af, const void *src,
  319. char *dst, int size)
  320. {
  321. PJ_ASSERT_RETURN(src && dst && size, PJ_EINVAL);
  322. *dst = '\0';
  323. PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EAFNOTSUP);
  324. #if defined(PJ_SOCK_HAS_INET_NTOP) && PJ_SOCK_HAS_INET_NTOP != 0
  325. /*
  326. * Implementation using inet_ntop()
  327. */
  328. if (inet_ntop(af, src, dst, size) == NULL) {
  329. pj_status_t status = pj_get_netos_error();
  330. if (status == PJ_SUCCESS)
  331. status = PJ_EUNKNOWN;
  332. return status;
  333. }
  334. return PJ_SUCCESS;
  335. #elif defined(PJ_WIN32) || defined(PJ_WIN32_WINCE)
  336. /*
  337. * Implementation on Windows, using WSAAddressToString().
  338. * Should also work on Unicode systems.
  339. */
  340. {
  341. PJ_DECL_UNICODE_TEMP_BUF(wtempaddr,PJ_INET6_ADDRSTRLEN)
  342. pj_sockaddr sock_addr;
  343. DWORD addr_len, addr_str_len;
  344. int rc;
  345. pj_bzero(&sock_addr, sizeof(sock_addr));
  346. sock_addr.addr.sa_family = (pj_uint16_t)af;
  347. if (af == PJ_AF_INET) {
  348. if (size < PJ_INET_ADDRSTRLEN)
  349. return PJ_ETOOSMALL;
  350. pj_memcpy(&sock_addr.ipv4.sin_addr, src, 4);
  351. addr_len = sizeof(pj_sockaddr_in);
  352. addr_str_len = PJ_INET_ADDRSTRLEN;
  353. } else if (af == PJ_AF_INET6) {
  354. if (size < PJ_INET6_ADDRSTRLEN)
  355. return PJ_ETOOSMALL;
  356. pj_memcpy(&sock_addr.ipv6.sin6_addr, src, 16);
  357. addr_len = sizeof(pj_sockaddr_in6);
  358. addr_str_len = PJ_INET6_ADDRSTRLEN;
  359. } else {
  360. pj_assert(!"Unsupported address family");
  361. return PJ_EAFNOTSUP;
  362. }
  363. #if PJ_NATIVE_STRING_IS_UNICODE
  364. rc = WSAAddressToString((LPSOCKADDR)&sock_addr, addr_len,
  365. NULL, wtempaddr, &addr_str_len);
  366. if (rc == 0) {
  367. pj_unicode_to_ansi(wtempaddr, wcslen(wtempaddr), dst, size);
  368. }
  369. #else
  370. rc = WSAAddressToString((LPSOCKADDR)&sock_addr, addr_len,
  371. NULL, dst, &addr_str_len);
  372. #endif
  373. if (rc != 0) {
  374. pj_status_t status = pj_get_netos_error();
  375. if (status == PJ_SUCCESS)
  376. status = PJ_EUNKNOWN;
  377. return status;
  378. }
  379. return PJ_SUCCESS;
  380. }
  381. #elif !defined(PJ_HAS_IPV6) || PJ_HAS_IPV6==0
  382. /* IPv6 support is disabled, just return error without raising assertion */
  383. return PJ_EIPV6NOTSUP;
  384. #else
  385. pj_assert(!"Not supported");
  386. return PJ_EIPV6NOTSUP;
  387. #endif
  388. }
  389. /*
  390. * Get hostname.
  391. */
  392. PJ_DEF(const pj_str_t*) pj_gethostname(void)
  393. {
  394. static char buf[PJ_MAX_HOSTNAME];
  395. static pj_str_t hostname;
  396. PJ_CHECK_STACK();
  397. if (hostname.ptr == NULL) {
  398. hostname.ptr = buf;
  399. if (gethostname(buf, sizeof(buf)) != 0) {
  400. hostname.ptr[0] = '\0';
  401. hostname.slen = 0;
  402. } else {
  403. hostname.slen = strlen(buf);
  404. }
  405. }
  406. return &hostname;
  407. }
  408. #if defined(PJ_WIN32)
  409. /*
  410. * Create new socket/endpoint for communication and returns a descriptor.
  411. */
  412. PJ_DEF(pj_status_t) pj_sock_socket(int af,
  413. int type,
  414. int proto,
  415. pj_sock_t *sock)
  416. {
  417. PJ_CHECK_STACK();
  418. /* Sanity checks. */
  419. PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL);
  420. PJ_ASSERT_RETURN((unsigned)PJ_INVALID_SOCKET==INVALID_SOCKET,
  421. (*sock=PJ_INVALID_SOCKET, PJ_EINVAL));
  422. *sock = WSASocket(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED);
  423. if (*sock == PJ_INVALID_SOCKET)
  424. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  425. #if PJ_SOCK_DISABLE_WSAECONNRESET && \
  426. (!defined(PJ_WIN32_WINCE) || PJ_WIN32_WINCE==0)
  427. #ifndef SIO_UDP_CONNRESET
  428. #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
  429. #endif
  430. /* Disable WSAECONNRESET for UDP.
  431. * See https://trac.pjsip.org/repos/ticket/1197
  432. */
  433. if (type==PJ_SOCK_DGRAM) {
  434. DWORD dwBytesReturned = 0;
  435. BOOL bNewBehavior = FALSE;
  436. DWORD rc;
  437. rc = WSAIoctl(*sock, SIO_UDP_CONNRESET,
  438. &bNewBehavior, sizeof(bNewBehavior),
  439. NULL, 0, &dwBytesReturned,
  440. NULL, NULL);
  441. if (rc==SOCKET_ERROR) {
  442. // Ignored..
  443. }
  444. }
  445. #endif
  446. return PJ_SUCCESS;
  447. }
  448. #else
  449. /*
  450. * Create new socket/endpoint for communication and returns a descriptor.
  451. */
  452. PJ_DEF(pj_status_t) pj_sock_socket(int af,
  453. int type,
  454. int proto,
  455. pj_sock_t *sock)
  456. {
  457. PJ_CHECK_STACK();
  458. /* Sanity checks. */
  459. PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL);
  460. PJ_ASSERT_RETURN(PJ_INVALID_SOCKET==-1,
  461. (*sock=PJ_INVALID_SOCKET, PJ_EINVAL));
  462. *sock = socket(af, type, proto);
  463. if (*sock == PJ_INVALID_SOCKET)
  464. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  465. else {
  466. pj_int32_t val = 1;
  467. if (type == pj_SOCK_STREAM()) {
  468. pj_sock_setsockopt(*sock, pj_SOL_SOCKET(), pj_SO_NOSIGPIPE(),
  469. &val, sizeof(val));
  470. }
  471. #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
  472. PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
  473. if (type == pj_SOCK_DGRAM()) {
  474. pj_sock_setsockopt(*sock, pj_SOL_SOCKET(), SO_NOSIGPIPE,
  475. &val, sizeof(val));
  476. }
  477. #endif
  478. return PJ_SUCCESS;
  479. }
  480. }
  481. #endif
  482. /*
  483. * Bind socket.
  484. */
  485. PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock,
  486. const pj_sockaddr_t *addr,
  487. int len)
  488. {
  489. PJ_CHECK_STACK();
  490. PJ_ASSERT_RETURN(addr && len >= (int)sizeof(struct sockaddr_in), PJ_EINVAL);
  491. CHECK_ADDR_LEN(addr, len);
  492. if (bind(sock, (struct sockaddr*)addr, len) != 0)
  493. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  494. else
  495. return PJ_SUCCESS;
  496. }
  497. /*
  498. * Bind socket.
  499. */
  500. PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sock,
  501. pj_uint32_t addr32,
  502. pj_uint16_t port)
  503. {
  504. pj_sockaddr_in addr;
  505. PJ_CHECK_STACK();
  506. PJ_SOCKADDR_SET_LEN(&addr, sizeof(pj_sockaddr_in));
  507. addr.sin_family = PJ_AF_INET;
  508. pj_bzero(addr.sin_zero, sizeof(addr.sin_zero));
  509. addr.sin_addr.s_addr = pj_htonl(addr32);
  510. addr.sin_port = pj_htons(port);
  511. return pj_sock_bind(sock, &addr, sizeof(pj_sockaddr_in));
  512. }
  513. /*
  514. * Close socket.
  515. */
  516. PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sock)
  517. {
  518. int rc;
  519. PJ_CHECK_STACK();
  520. #if defined(PJ_WIN32) && PJ_WIN32!=0 || \
  521. defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
  522. rc = closesocket(sock);
  523. #else
  524. rc = close(sock);
  525. #endif
  526. if (rc != 0)
  527. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  528. else
  529. return PJ_SUCCESS;
  530. }
  531. /*
  532. * Get remote's name.
  533. */
  534. PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sock,
  535. pj_sockaddr_t *addr,
  536. int *namelen)
  537. {
  538. PJ_CHECK_STACK();
  539. if (getpeername(sock, (struct sockaddr*)addr, (socklen_t*)namelen) != 0)
  540. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  541. else {
  542. PJ_SOCKADDR_RESET_LEN(addr);
  543. return PJ_SUCCESS;
  544. }
  545. }
  546. /*
  547. * Get socket name.
  548. */
  549. PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sock,
  550. pj_sockaddr_t *addr,
  551. int *namelen)
  552. {
  553. PJ_CHECK_STACK();
  554. if (getsockname(sock, (struct sockaddr*)addr, (socklen_t*)namelen) != 0)
  555. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  556. else {
  557. PJ_SOCKADDR_RESET_LEN(addr);
  558. return PJ_SUCCESS;
  559. }
  560. }
  561. /*
  562. * Send data
  563. */
  564. PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock,
  565. const void *buf,
  566. pj_ssize_t *len,
  567. unsigned flags)
  568. {
  569. PJ_CHECK_STACK();
  570. PJ_ASSERT_RETURN(len, PJ_EINVAL);
  571. #ifdef MSG_NOSIGNAL
  572. /* Suppress SIGPIPE. See https://trac.pjsip.org/repos/ticket/1538 */
  573. flags |= MSG_NOSIGNAL;
  574. #endif
  575. *len = send(sock, (const char*)buf, *len, flags);
  576. if (*len < 0)
  577. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  578. else
  579. return PJ_SUCCESS;
  580. }
  581. /*
  582. * Send data.
  583. */
  584. PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock,
  585. const void *buf,
  586. pj_ssize_t *len,
  587. unsigned flags,
  588. const pj_sockaddr_t *to,
  589. int tolen)
  590. {
  591. PJ_CHECK_STACK();
  592. PJ_ASSERT_RETURN(len, PJ_EINVAL);
  593. CHECK_ADDR_LEN(to, tolen);
  594. *len = sendto(sock, (const char*)buf, *len, flags,
  595. (const struct sockaddr*)to, tolen);
  596. if (*len < 0)
  597. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  598. else
  599. return PJ_SUCCESS;
  600. }
  601. /*
  602. * Receive data.
  603. */
  604. PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock,
  605. void *buf,
  606. pj_ssize_t *len,
  607. unsigned flags)
  608. {
  609. PJ_CHECK_STACK();
  610. PJ_ASSERT_RETURN(buf && len, PJ_EINVAL);
  611. *len = recv(sock, (char*)buf, *len, flags);
  612. if (*len < 0)
  613. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  614. else
  615. return PJ_SUCCESS;
  616. }
  617. /*
  618. * Receive data.
  619. */
  620. PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
  621. void *buf,
  622. pj_ssize_t *len,
  623. unsigned flags,
  624. pj_sockaddr_t *from,
  625. int *fromlen)
  626. {
  627. PJ_CHECK_STACK();
  628. PJ_ASSERT_RETURN(buf && len, PJ_EINVAL);
  629. *len = recvfrom(sock, (char*)buf, *len, flags,
  630. (struct sockaddr*)from, (socklen_t*)fromlen);
  631. if (*len < 0)
  632. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  633. else {
  634. if (from) {
  635. PJ_SOCKADDR_RESET_LEN(from);
  636. }
  637. return PJ_SUCCESS;
  638. }
  639. }
  640. /*
  641. * Get socket option.
  642. */
  643. PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sock,
  644. pj_uint16_t level,
  645. pj_uint16_t optname,
  646. void *optval,
  647. int *optlen)
  648. {
  649. PJ_CHECK_STACK();
  650. PJ_ASSERT_RETURN(optval && optlen, PJ_EINVAL);
  651. if (getsockopt(sock, level, optname, (char*)optval, (socklen_t*)optlen)!=0)
  652. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  653. else
  654. return PJ_SUCCESS;
  655. }
  656. /*
  657. * Set socket option.
  658. */
  659. PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock,
  660. pj_uint16_t level,
  661. pj_uint16_t optname,
  662. const void *optval,
  663. int optlen)
  664. {
  665. PJ_CHECK_STACK();
  666. if (setsockopt(sock, level, optname, (const char*)optval, optlen) != 0)
  667. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  668. else
  669. return PJ_SUCCESS;
  670. }
  671. /*
  672. * Connect socket.
  673. */
  674. PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock,
  675. const pj_sockaddr_t *addr,
  676. int namelen)
  677. {
  678. PJ_CHECK_STACK();
  679. if (connect(sock, (struct sockaddr*)addr, namelen) != 0)
  680. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  681. else
  682. return PJ_SUCCESS;
  683. }
  684. /*
  685. * Shutdown socket.
  686. */
  687. #if PJ_HAS_TCP
  688. PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sock,
  689. int how)
  690. {
  691. PJ_CHECK_STACK();
  692. if (shutdown(sock, how) != 0)
  693. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  694. else
  695. return PJ_SUCCESS;
  696. }
  697. /*
  698. * Start listening to incoming connections.
  699. */
  700. PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sock,
  701. int backlog)
  702. {
  703. PJ_CHECK_STACK();
  704. if (listen(sock, backlog) != 0)
  705. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  706. else
  707. return PJ_SUCCESS;
  708. }
  709. /*
  710. * Accept incoming connections
  711. */
  712. PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t serverfd,
  713. pj_sock_t *newsock,
  714. pj_sockaddr_t *addr,
  715. int *addrlen)
  716. {
  717. PJ_CHECK_STACK();
  718. PJ_ASSERT_RETURN(newsock != NULL, PJ_EINVAL);
  719. #if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
  720. if (addr) {
  721. PJ_SOCKADDR_SET_LEN(addr, *addrlen);
  722. }
  723. #endif
  724. *newsock = accept(serverfd, (struct sockaddr*)addr, (socklen_t*)addrlen);
  725. if (*newsock==PJ_INVALID_SOCKET)
  726. return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
  727. else {
  728. #if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
  729. if (addr) {
  730. PJ_SOCKADDR_RESET_LEN(addr);
  731. }
  732. #endif
  733. return PJ_SUCCESS;
  734. }
  735. }
  736. #endif /* PJ_HAS_TCP */