espidf_socket.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. /*
  2. * Copyright (C) 2021 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "platform_api_vmcore.h"
  6. #include "platform_api_extension.h"
  7. #include "libc_errno.h"
  8. #include <arpa/inet.h>
  9. #include <netdb.h>
  10. #include <netinet/tcp.h>
  11. #include <netinet/in.h>
  12. static bool
  13. textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out,
  14. socklen_t *out_len)
  15. {
  16. struct sockaddr_in *v4;
  17. #ifdef IPPROTO_IPV6
  18. struct sockaddr_in6 *v6;
  19. #endif
  20. assert(textual);
  21. v4 = (struct sockaddr_in *)out;
  22. if (inet_pton(AF_INET, textual, &v4->sin_addr.s_addr) == 1) {
  23. v4->sin_family = AF_INET;
  24. v4->sin_port = htons(port);
  25. *out_len = sizeof(struct sockaddr_in);
  26. return true;
  27. }
  28. #ifdef IPPROTO_IPV6
  29. v6 = (struct sockaddr_in6 *)out;
  30. if (inet_pton(AF_INET6, textual, &v6->sin6_addr.s6_addr) == 1) {
  31. v6->sin6_family = AF_INET6;
  32. v6->sin6_port = htons(port);
  33. *out_len = sizeof(struct sockaddr_in6);
  34. return true;
  35. }
  36. #endif
  37. return false;
  38. }
  39. static int
  40. sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr,
  41. bh_sockaddr_t *bh_sockaddr)
  42. {
  43. switch (sockaddr->sa_family) {
  44. case AF_INET:
  45. {
  46. struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
  47. bh_sockaddr->port = ntohs(addr->sin_port);
  48. bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr);
  49. bh_sockaddr->is_ipv4 = true;
  50. return BHT_OK;
  51. }
  52. #ifdef IPPROTO_IPV6
  53. case AF_INET6:
  54. {
  55. struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr;
  56. size_t i;
  57. bh_sockaddr->port = ntohs(addr->sin6_port);
  58. for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6)
  59. / sizeof(bh_sockaddr->addr_buffer.ipv6[0]);
  60. i++) {
  61. uint16 part_addr = addr->sin6_addr.s6_addr[i * 2]
  62. | (addr->sin6_addr.s6_addr[i * 2 + 1] << 8);
  63. bh_sockaddr->addr_buffer.ipv6[i] = ntohs(part_addr);
  64. }
  65. bh_sockaddr->is_ipv4 = false;
  66. return BHT_OK;
  67. }
  68. #endif
  69. default:
  70. errno = EAFNOSUPPORT;
  71. return BHT_ERROR;
  72. }
  73. }
  74. static void
  75. bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr,
  76. struct sockaddr_storage *sockaddr, socklen_t *socklen)
  77. {
  78. if (bh_sockaddr->is_ipv4) {
  79. struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
  80. addr->sin_port = htons(bh_sockaddr->port);
  81. addr->sin_family = AF_INET;
  82. addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_buffer.ipv4);
  83. *socklen = sizeof(*addr);
  84. }
  85. #ifdef IPPROTO_IPV6
  86. else {
  87. struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr;
  88. size_t i;
  89. addr->sin6_port = htons(bh_sockaddr->port);
  90. addr->sin6_family = AF_INET6;
  91. for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6)
  92. / sizeof(bh_sockaddr->addr_buffer.ipv6[0]);
  93. i++) {
  94. uint16 part_addr = htons(bh_sockaddr->addr_buffer.ipv6[i]);
  95. addr->sin6_addr.s6_addr[i * 2] = 0xff & part_addr;
  96. addr->sin6_addr.s6_addr[i * 2 + 1] = (0xff00 & part_addr) >> 8;
  97. }
  98. *socklen = sizeof(*addr);
  99. }
  100. #endif
  101. }
  102. int
  103. os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
  104. {
  105. int af = is_ipv4 ? AF_INET : AF_INET6;
  106. if (!sock) {
  107. return BHT_ERROR;
  108. }
  109. if (is_tcp) {
  110. *sock = socket(af, SOCK_STREAM, IPPROTO_TCP);
  111. }
  112. else {
  113. *sock = socket(af, SOCK_DGRAM, 0);
  114. }
  115. return (*sock == -1) ? BHT_ERROR : BHT_OK;
  116. }
  117. int
  118. os_socket_bind(bh_socket_t socket, const char *host, int *port)
  119. {
  120. struct sockaddr_storage addr = { 0 };
  121. struct linger ling;
  122. socklen_t socklen;
  123. int ret;
  124. assert(host);
  125. assert(port);
  126. ling.l_onoff = 1;
  127. ling.l_linger = 0;
  128. if (!textual_addr_to_sockaddr(host, *port, (struct sockaddr *)&addr,
  129. &socklen)) {
  130. goto fail;
  131. }
  132. ret = setsockopt(socket, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
  133. if (ret < 0) {
  134. goto fail;
  135. }
  136. ret = bind(socket, (struct sockaddr *)&addr, socklen);
  137. if (ret < 0) {
  138. goto fail;
  139. }
  140. socklen = sizeof(addr);
  141. if (getsockname(socket, (void *)&addr, &socklen) == -1) {
  142. goto fail;
  143. }
  144. if (addr.ss_family == AF_INET) {
  145. *port = ntohs(((struct sockaddr_in *)&addr)->sin_port);
  146. }
  147. else {
  148. #ifdef IPPROTO_IPV6
  149. *port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port);
  150. #else
  151. goto fail;
  152. #endif
  153. }
  154. return BHT_OK;
  155. fail:
  156. return BHT_ERROR;
  157. }
  158. int
  159. os_socket_settimeout(bh_socket_t socket, uint64 timeout_us)
  160. {
  161. struct timeval tv;
  162. tv.tv_sec = timeout_us / 1000000UL;
  163. tv.tv_usec = timeout_us % 1000000UL;
  164. if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv,
  165. sizeof(tv))
  166. != 0) {
  167. return BHT_ERROR;
  168. }
  169. return BHT_OK;
  170. }
  171. int
  172. os_socket_listen(bh_socket_t socket, int max_client)
  173. {
  174. if (listen(socket, max_client) != 0) {
  175. return BHT_ERROR;
  176. }
  177. return BHT_OK;
  178. }
  179. int
  180. os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
  181. unsigned int *addrlen)
  182. {
  183. *sock = accept(server_sock, addr, (socklen_t *)addrlen);
  184. if (*sock < 0) {
  185. return BHT_ERROR;
  186. }
  187. return BHT_OK;
  188. }
  189. int
  190. os_socket_connect(bh_socket_t socket, const char *addr, int port)
  191. {
  192. struct sockaddr_storage addr_in = { 0 };
  193. socklen_t addr_len;
  194. int ret = 0;
  195. if (!textual_addr_to_sockaddr(addr, port, (struct sockaddr *)&addr_in,
  196. &addr_len)) {
  197. return BHT_ERROR;
  198. }
  199. ret = connect(socket, (struct sockaddr *)&addr_in, addr_len);
  200. if (ret == -1) {
  201. return BHT_ERROR;
  202. }
  203. return BHT_OK;
  204. }
  205. int
  206. os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
  207. {
  208. return recv(socket, buf, len, 0);
  209. }
  210. int
  211. os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
  212. bh_sockaddr_t *src_addr)
  213. {
  214. struct sockaddr_storage sock_addr = { 0 };
  215. socklen_t socklen = sizeof(sock_addr);
  216. int ret;
  217. ret = recvfrom(socket, buf, len, flags, (struct sockaddr *)&sock_addr,
  218. &socklen);
  219. if (ret < 0) {
  220. return ret;
  221. }
  222. if (src_addr && socklen > 0) {
  223. if (sockaddr_to_bh_sockaddr((struct sockaddr *)&sock_addr, src_addr)
  224. == BHT_ERROR) {
  225. return -1;
  226. }
  227. }
  228. else if (src_addr) {
  229. memset(src_addr, 0, sizeof(*src_addr));
  230. }
  231. return ret;
  232. }
  233. int
  234. os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
  235. {
  236. return send(socket, buf, len, 0);
  237. }
  238. int
  239. os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
  240. int flags, const bh_sockaddr_t *dest_addr)
  241. {
  242. struct sockaddr_storage sock_addr = { 0 };
  243. socklen_t socklen = 0;
  244. bh_sockaddr_to_sockaddr(dest_addr, &sock_addr, &socklen);
  245. return sendto(socket, buf, len, flags, (const struct sockaddr *)&sock_addr,
  246. socklen);
  247. }
  248. int
  249. os_socket_close(bh_socket_t socket)
  250. {
  251. close(socket);
  252. return BHT_OK;
  253. }
  254. __wasi_errno_t
  255. os_socket_shutdown(bh_socket_t socket)
  256. {
  257. if (shutdown(socket, O_RDWR) != 0) {
  258. return convert_errno(errno);
  259. }
  260. return __WASI_ESUCCESS;
  261. }
  262. int
  263. os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
  264. {
  265. if (!cp)
  266. return BHT_ERROR;
  267. if (is_ipv4) {
  268. if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
  269. return BHT_ERROR;
  270. }
  271. /* Note: ntohl(INADDR_NONE) == INADDR_NONE */
  272. out->ipv4 = ntohl(out->ipv4);
  273. }
  274. else {
  275. #ifdef IPPROTO_IPV6
  276. if (inet_pton(AF_INET6, cp, out->ipv6) != 1) {
  277. return BHT_ERROR;
  278. }
  279. for (int i = 0; i < 8; i++) {
  280. out->ipv6[i] = ntohs(out->ipv6[i]);
  281. }
  282. #else
  283. errno = EAFNOSUPPORT;
  284. return BHT_ERROR;
  285. #endif
  286. }
  287. return BHT_OK;
  288. }
  289. static int
  290. getaddrinfo_error_to_errno(int error)
  291. {
  292. switch (error) {
  293. case EAI_AGAIN:
  294. return EAGAIN;
  295. case EAI_FAIL:
  296. return EFAULT;
  297. case EAI_MEMORY:
  298. return ENOMEM;
  299. default:
  300. return EINVAL;
  301. }
  302. }
  303. static int
  304. is_addrinfo_supported(struct addrinfo *info)
  305. {
  306. return
  307. // Allow only IPv4 and IPv6
  308. (info->ai_family == AF_INET || info->ai_family == AF_INET6)
  309. // Allow only UDP and TCP
  310. && (info->ai_socktype == SOCK_DGRAM || info->ai_socktype == SOCK_STREAM)
  311. && (info->ai_protocol == IPPROTO_TCP
  312. || info->ai_protocol == IPPROTO_UDP);
  313. }
  314. int
  315. os_socket_addr_resolve(const char *host, const char *service,
  316. uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
  317. bh_addr_info_t *addr_info, size_t addr_info_size,
  318. size_t *max_info_size)
  319. {
  320. struct addrinfo hints = { 0 }, *res, *result;
  321. int hints_enabled = hint_is_tcp || hint_is_ipv4;
  322. int ret;
  323. size_t pos = 0;
  324. if (hints_enabled) {
  325. if (hint_is_ipv4) {
  326. hints.ai_family = *hint_is_ipv4 ? AF_INET : AF_INET6;
  327. }
  328. if (hint_is_tcp) {
  329. hints.ai_socktype = *hint_is_tcp ? SOCK_STREAM : SOCK_DGRAM;
  330. }
  331. }
  332. ret = getaddrinfo(host, strlen(service) == 0 ? NULL : service,
  333. hints_enabled ? &hints : NULL, &result);
  334. if (ret != BHT_OK) {
  335. errno = getaddrinfo_error_to_errno(ret);
  336. return BHT_ERROR;
  337. }
  338. res = result;
  339. while (res) {
  340. if (addr_info_size > pos) {
  341. if (!is_addrinfo_supported(res)) {
  342. res = res->ai_next;
  343. continue;
  344. }
  345. ret =
  346. sockaddr_to_bh_sockaddr(res->ai_addr, &addr_info[pos].sockaddr);
  347. if (ret == BHT_ERROR) {
  348. freeaddrinfo(result);
  349. return BHT_ERROR;
  350. }
  351. addr_info[pos].is_tcp = res->ai_socktype == SOCK_STREAM;
  352. }
  353. pos++;
  354. res = res->ai_next;
  355. }
  356. *max_info_size = pos;
  357. freeaddrinfo(result);
  358. return BHT_OK;
  359. }
  360. static int
  361. os_socket_setbooloption(bh_socket_t socket, int level, int optname,
  362. bool is_enabled)
  363. {
  364. int option = (int)is_enabled;
  365. if (setsockopt(socket, level, optname, &option, sizeof(option)) != 0) {
  366. return BHT_ERROR;
  367. }
  368. return BHT_OK;
  369. }
  370. static int
  371. os_socket_getbooloption(bh_socket_t socket, int level, int optname,
  372. bool *is_enabled)
  373. {
  374. assert(is_enabled);
  375. int optval;
  376. socklen_t optval_size = sizeof(optval);
  377. if (getsockopt(socket, level, optname, &optval, &optval_size) != 0) {
  378. return BHT_ERROR;
  379. }
  380. *is_enabled = (bool)optval;
  381. return BHT_OK;
  382. }
  383. int
  384. os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz)
  385. {
  386. int buf_size_int = (int)bufsiz;
  387. if (setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buf_size_int,
  388. sizeof(buf_size_int))
  389. != 0) {
  390. return BHT_ERROR;
  391. }
  392. return BHT_OK;
  393. }
  394. int
  395. os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz)
  396. {
  397. assert(bufsiz);
  398. int buf_size_int;
  399. socklen_t bufsiz_len = sizeof(buf_size_int);
  400. if (getsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buf_size_int, &bufsiz_len)
  401. != 0) {
  402. return BHT_ERROR;
  403. }
  404. *bufsiz = (size_t)buf_size_int;
  405. return BHT_OK;
  406. }
  407. int
  408. os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz)
  409. {
  410. int buf_size_int = (int)bufsiz;
  411. if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buf_size_int,
  412. sizeof(buf_size_int))
  413. != 0) {
  414. return BHT_ERROR;
  415. }
  416. return BHT_OK;
  417. }
  418. int
  419. os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz)
  420. {
  421. assert(bufsiz);
  422. int buf_size_int;
  423. socklen_t bufsiz_len = sizeof(buf_size_int);
  424. if (getsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buf_size_int, &bufsiz_len)
  425. != 0) {
  426. return BHT_ERROR;
  427. }
  428. *bufsiz = (size_t)buf_size_int;
  429. return BHT_OK;
  430. }
  431. int
  432. os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled)
  433. {
  434. return os_socket_setbooloption(socket, SOL_SOCKET, SO_KEEPALIVE,
  435. is_enabled);
  436. }
  437. int
  438. os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled)
  439. {
  440. return os_socket_getbooloption(socket, SOL_SOCKET, SO_KEEPALIVE,
  441. is_enabled);
  442. }
  443. int
  444. os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled)
  445. {
  446. return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEADDR,
  447. is_enabled);
  448. }
  449. int
  450. os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled)
  451. {
  452. return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEADDR,
  453. is_enabled);
  454. }
  455. int
  456. os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled)
  457. {
  458. #if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */
  459. return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEPORT,
  460. is_enabled);
  461. #else
  462. errno = ENOTSUP;
  463. return BHT_ERROR;
  464. #endif /* defined(SO_REUSEPORT) */
  465. }
  466. int
  467. os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled)
  468. {
  469. #if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */
  470. return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEPORT,
  471. is_enabled);
  472. #else
  473. errno = ENOTSUP;
  474. return BHT_ERROR;
  475. #endif /* defined(SO_REUSEPORT) */
  476. }
  477. int
  478. os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s)
  479. {
  480. struct linger linger_opts = { .l_onoff = (int)is_enabled,
  481. .l_linger = linger_s };
  482. if (setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_opts,
  483. sizeof(linger_opts))
  484. != 0) {
  485. return BHT_ERROR;
  486. }
  487. return BHT_OK;
  488. }
  489. int
  490. os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s)
  491. {
  492. assert(is_enabled);
  493. assert(linger_s);
  494. struct linger linger_opts;
  495. socklen_t linger_opts_len = sizeof(linger_opts);
  496. if (getsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_opts,
  497. &linger_opts_len)
  498. != 0) {
  499. return BHT_ERROR;
  500. }
  501. *linger_s = linger_opts.l_linger;
  502. *is_enabled = (bool)linger_opts.l_onoff;
  503. return BHT_OK;
  504. }
  505. int
  506. os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled)
  507. {
  508. return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_NODELAY,
  509. is_enabled);
  510. }
  511. int
  512. os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled)
  513. {
  514. return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_NODELAY,
  515. is_enabled);
  516. }
  517. int
  518. os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled)
  519. {
  520. #ifdef TCP_QUICKACK
  521. return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_QUICKACK,
  522. is_enabled);
  523. #else
  524. errno = ENOSYS;
  525. return BHT_ERROR;
  526. #endif
  527. }
  528. int
  529. os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled)
  530. {
  531. #ifdef TCP_QUICKACK
  532. return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_QUICKACK,
  533. is_enabled);
  534. #else
  535. errno = ENOSYS;
  536. return BHT_ERROR;
  537. #endif
  538. }
  539. int
  540. os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s)
  541. {
  542. int time_s_int = (int)time_s;
  543. #ifdef TCP_KEEPIDLE
  544. if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int,
  545. sizeof(time_s_int))
  546. != 0) {
  547. return BHT_ERROR;
  548. }
  549. return BHT_OK;
  550. #elif defined(TCP_KEEPALIVE)
  551. if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int,
  552. sizeof(time_s_int))
  553. != 0) {
  554. return BHT_ERROR;
  555. }
  556. return BHT_OK;
  557. #else
  558. errno = ENOSYS;
  559. return BHT_ERROR;
  560. #endif
  561. }
  562. int
  563. os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s)
  564. {
  565. assert(time_s);
  566. int time_s_int;
  567. socklen_t time_s_len = sizeof(time_s_int);
  568. #ifdef TCP_KEEPIDLE
  569. if (getsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int, &time_s_len)
  570. != 0) {
  571. return BHT_ERROR;
  572. }
  573. *time_s = (uint32)time_s_int;
  574. return BHT_OK;
  575. #elif defined(TCP_KEEPALIVE)
  576. if (getsockopt(socket, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int, &time_s_len)
  577. != 0) {
  578. return BHT_ERROR;
  579. }
  580. *time_s = (uint32)time_s_int;
  581. return BHT_OK;
  582. #else
  583. errno = ENOSYS;
  584. return BHT_ERROR;
  585. #endif
  586. }
  587. int
  588. os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s)
  589. {
  590. int time_s_int = (int)time_s;
  591. #ifdef TCP_KEEPINTVL
  592. if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &time_s_int,
  593. sizeof(time_s_int))
  594. != 0) {
  595. return BHT_ERROR;
  596. }
  597. return BHT_OK;
  598. #else
  599. errno = ENOSYS;
  600. return BHT_ERROR;
  601. #endif
  602. }
  603. int
  604. os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s)
  605. {
  606. #ifdef TCP_KEEPINTVL
  607. assert(time_s);
  608. int time_s_int;
  609. socklen_t time_s_len = sizeof(time_s_int);
  610. if (getsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &time_s_int, &time_s_len)
  611. != 0) {
  612. return BHT_ERROR;
  613. }
  614. *time_s = (uint32)time_s_int;
  615. return BHT_OK;
  616. #else
  617. errno = ENOSYS;
  618. return BHT_ERROR;
  619. #endif
  620. }
  621. int
  622. os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled)
  623. {
  624. #ifdef TCP_FASTOPEN_CONNECT
  625. return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
  626. is_enabled);
  627. #else
  628. errno = ENOSYS;
  629. return BHT_ERROR;
  630. #endif
  631. }
  632. int
  633. os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled)
  634. {
  635. #ifdef TCP_FASTOPEN_CONNECT
  636. return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
  637. is_enabled);
  638. #else
  639. errno = ENOSYS;
  640. return BHT_ERROR;
  641. #endif
  642. }
  643. int
  644. os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled)
  645. {
  646. if (ipv6) {
  647. #ifdef IPPROTO_IPV6
  648. return os_socket_setbooloption(socket, IPPROTO_IPV6,
  649. IPV6_MULTICAST_LOOP, is_enabled);
  650. #else
  651. errno = EAFNOSUPPORT;
  652. return BHT_ERROR;
  653. #endif
  654. }
  655. else {
  656. return os_socket_setbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP,
  657. is_enabled);
  658. }
  659. }
  660. int
  661. os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled)
  662. {
  663. if (ipv6) {
  664. #ifdef IPPROTO_IPV6
  665. return os_socket_getbooloption(socket, IPPROTO_IPV6,
  666. IPV6_MULTICAST_LOOP, is_enabled);
  667. #else
  668. errno = EAFNOSUPPORT;
  669. return BHT_ERROR;
  670. #endif
  671. }
  672. else {
  673. return os_socket_getbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP,
  674. is_enabled);
  675. }
  676. }
  677. int
  678. os_socket_set_ip_add_membership(bh_socket_t socket,
  679. bh_ip_addr_buffer_t *imr_multiaddr,
  680. uint32_t imr_interface, bool is_ipv6)
  681. {
  682. assert(imr_multiaddr);
  683. if (is_ipv6) {
  684. #if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN)
  685. struct ipv6_mreq mreq;
  686. for (int i = 0; i < 8; i++) {
  687. ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =
  688. imr_multiaddr->ipv6[i];
  689. }
  690. mreq.ipv6mr_interface = imr_interface;
  691. if (setsockopt(socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
  692. sizeof(mreq))
  693. != 0) {
  694. return BHT_ERROR;
  695. }
  696. #else
  697. errno = EAFNOSUPPORT;
  698. return BHT_ERROR;
  699. #endif
  700. }
  701. else {
  702. struct ip_mreq mreq;
  703. mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4;
  704. mreq.imr_interface.s_addr = imr_interface;
  705. if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
  706. sizeof(mreq))
  707. != 0) {
  708. return BHT_ERROR;
  709. }
  710. }
  711. return BHT_OK;
  712. }
  713. int
  714. os_socket_set_ip_drop_membership(bh_socket_t socket,
  715. bh_ip_addr_buffer_t *imr_multiaddr,
  716. uint32_t imr_interface, bool is_ipv6)
  717. {
  718. assert(imr_multiaddr);
  719. if (is_ipv6) {
  720. #if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN)
  721. struct ipv6_mreq mreq;
  722. for (int i = 0; i < 8; i++) {
  723. ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =
  724. imr_multiaddr->ipv6[i];
  725. }
  726. mreq.ipv6mr_interface = imr_interface;
  727. if (setsockopt(socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq,
  728. sizeof(mreq))
  729. != 0) {
  730. return BHT_ERROR;
  731. }
  732. #else
  733. errno = EAFNOSUPPORT;
  734. return BHT_ERROR;
  735. #endif
  736. }
  737. else {
  738. struct ip_mreq mreq;
  739. mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4;
  740. mreq.imr_interface.s_addr = imr_interface;
  741. if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq,
  742. sizeof(mreq))
  743. != 0) {
  744. return BHT_ERROR;
  745. }
  746. }
  747. return BHT_OK;
  748. }
  749. int
  750. os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s)
  751. {
  752. if (setsockopt(socket, IPPROTO_IP, IP_TTL, &ttl_s, sizeof(ttl_s)) != 0) {
  753. return BHT_ERROR;
  754. }
  755. return BHT_OK;
  756. }
  757. int
  758. os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s)
  759. {
  760. socklen_t opt_len = sizeof(*ttl_s);
  761. if (getsockopt(socket, IPPROTO_IP, IP_TTL, ttl_s, &opt_len) != 0) {
  762. return BHT_ERROR;
  763. }
  764. return BHT_OK;
  765. }
  766. int
  767. os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s)
  768. {
  769. if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl_s, sizeof(ttl_s))
  770. != 0) {
  771. return BHT_ERROR;
  772. }
  773. return BHT_OK;
  774. }
  775. int
  776. os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s)
  777. {
  778. socklen_t opt_len = sizeof(*ttl_s);
  779. if (getsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, ttl_s, &opt_len)
  780. != 0) {
  781. return BHT_ERROR;
  782. }
  783. return BHT_OK;
  784. }
  785. int
  786. os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled)
  787. {
  788. #ifdef IPPROTO_IPV6
  789. return os_socket_setbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
  790. is_enabled);
  791. #else
  792. errno = EAFNOSUPPORT;
  793. return BHT_ERROR;
  794. #endif
  795. }
  796. int
  797. os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled)
  798. {
  799. #ifdef IPPROTO_IPV6
  800. return os_socket_getbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
  801. is_enabled);
  802. #else
  803. errno = EAFNOSUPPORT;
  804. return BHT_ERROR;
  805. #endif
  806. }
  807. int
  808. os_socket_set_broadcast(bh_socket_t socket, bool is_enabled)
  809. {
  810. return os_socket_setbooloption(socket, SOL_SOCKET, SO_BROADCAST,
  811. is_enabled);
  812. }
  813. int
  814. os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled)
  815. {
  816. return os_socket_getbooloption(socket, SOL_SOCKET, SO_BROADCAST,
  817. is_enabled);
  818. }
  819. int
  820. os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us)
  821. {
  822. struct timeval tv;
  823. tv.tv_sec = timeout_us / 1000000UL;
  824. tv.tv_usec = timeout_us % 1000000UL;
  825. if (setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) != 0) {
  826. return BHT_ERROR;
  827. }
  828. return BHT_OK;
  829. }
  830. int
  831. os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us)
  832. {
  833. struct timeval tv;
  834. socklen_t tv_len = sizeof(tv);
  835. if (getsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, &tv_len) != 0) {
  836. return BHT_ERROR;
  837. }
  838. *timeout_us = (tv.tv_sec * 1000000UL) + tv.tv_usec;
  839. return BHT_OK;
  840. }
  841. int
  842. os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us)
  843. {
  844. struct timeval tv;
  845. tv.tv_sec = timeout_us / 1000000UL;
  846. tv.tv_usec = timeout_us % 1000000UL;
  847. if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) {
  848. return BHT_ERROR;
  849. }
  850. return BHT_OK;
  851. }
  852. int
  853. os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
  854. {
  855. struct timeval tv;
  856. socklen_t tv_len = sizeof(tv);
  857. if (getsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, &tv_len) != 0) {
  858. return BHT_ERROR;
  859. }
  860. *timeout_us = (tv.tv_sec * 1000000UL) + tv.tv_usec;
  861. return BHT_OK;
  862. }
  863. int
  864. os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
  865. {
  866. struct sockaddr_storage addr_storage = { 0 };
  867. socklen_t addr_len = sizeof(addr_storage);
  868. int ret;
  869. ret = getsockname(socket, (struct sockaddr *)&addr_storage, &addr_len);
  870. if (ret != BHT_OK) {
  871. return BHT_ERROR;
  872. }
  873. return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, sockaddr);
  874. }
  875. int
  876. os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
  877. {
  878. struct sockaddr_storage addr_storage = { 0 };
  879. socklen_t addr_len = sizeof(addr_storage);
  880. int ret;
  881. ret = getpeername(socket, (struct sockaddr *)&addr_storage, &addr_len);
  882. if (ret != BHT_OK) {
  883. return BHT_ERROR;
  884. }
  885. return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, sockaddr);
  886. }