zephyr_socket.c 25 KB

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