Skip to content

Commit bc63d24

Browse files
kr-tdkouba-atym
authored andcommitted
Improve networking (#7)
* Support get/set for flags on socket fds * Changes to support open62541 client/server * Fix mismatch of enum sizes between WASM and host * Improve zephyr sockets * Add explanation comment --------- Signed-off-by: Dan Kouba <dan@atym.io> Signed-off-by: Krisztian Szilvasi <34309983+kr-t@users.noreply.github.com> Co-authored-by: Dan Kouba <dan@atym.io>
1 parent d1a577e commit bc63d24

2 files changed

Lines changed: 70 additions & 10 deletions

File tree

core/shared/platform/zephyr/zephyr_file.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include <zephyr/fs/fs_sys.h>
1616
#include <zephyr/fs/littlefs.h>
1717

18+
#include <zephyr/net/socket.h>
19+
#include <zephyr/posix/fcntl.h> // F_GETFL, F_SETFL, O_NONBLOCK
20+
1821
/* Notes:
1922
* This is the implementation of a POSIX-like file system interface for Zephyr.
2023
* To manage our file descriptors, we created a struct `zephyr_fs_desc` that
@@ -275,6 +278,16 @@ os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags)
275278
{
276279
struct zephyr_fs_desc *ptr = NULL;
277280

281+
/* Sockets: reflect current non-blocking state */
282+
if (handle->is_sock) {
283+
int cur = zsock_fcntl(handle->fd, F_GETFL, 0);
284+
if (cur < 0)
285+
return convert_errno(errno);
286+
if (cur & O_NONBLOCK)
287+
*flags |= __WASI_FDFLAG_NONBLOCK;
288+
return __WASI_ESUCCESS;
289+
}
290+
278291
if (os_is_virtual_fd(handle->fd)) {
279292
*flags = 0;
280293
return __WASI_ESUCCESS;
@@ -298,6 +311,21 @@ os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags)
298311
__wasi_errno_t
299312
os_file_set_fdflags(os_file_handle handle, __wasi_fdflags_t flags)
300313
{
314+
/* Sockets: set/clear O_NONBLOCK */
315+
if (handle->is_sock) {
316+
int cur = zsock_fcntl(handle->fd, F_GETFL, 0);
317+
if (cur < 0)
318+
return convert_errno(errno);
319+
320+
bool want_nb = (flags & __WASI_FDFLAG_NONBLOCK) != 0;
321+
int newf = want_nb ? (cur | O_NONBLOCK) : (cur & ~O_NONBLOCK);
322+
323+
if (zsock_fcntl(handle->fd, F_SETFL, newf) < 0) {
324+
return convert_errno(errno);
325+
}
326+
return __WASI_ESUCCESS;
327+
}
328+
301329
if (os_is_virtual_fd(handle->fd)) {
302330
return __WASI_ESUCCESS;
303331
}

core/shared/platform/zephyr/zephyr_socket.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,23 @@ static bool
2222
textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out,
2323
socklen_t *out_len)
2424
{
25-
struct sockaddr_in *v4;
25+
struct sockaddr_in *v4 = (struct sockaddr_in *)out;
2626
#ifdef IPPROTO_IPV6
2727
struct sockaddr_in6 *v6;
2828
#endif
2929

3030
assert(textual);
3131

32-
v4 = (struct sockaddr_in *)out;
3332
if (zsock_inet_pton(AF_INET, textual, &v4->sin_addr.s_addr) == 1) {
3433
v4->sin_family = AF_INET;
3534
v4->sin_port = htons(port);
35+
/**
36+
* In `zephyr_socket.c` the method `textual_addr_to_sockaddr` takes the
37+
* multicast address of "224.0.0.22" and properly sets the sockaddr.
38+
* However, this fails when binding to the adapter for some reason.
39+
* Setting this to “0.0.0.0” works. This appears to be a bug in Zephyr.
40+
*/
41+
v4->sin_addr.s_addr = htonl(INADDR_ANY);
3642
*out_len = sizeof(struct sockaddr_in);
3743
return true;
3844
}
@@ -923,10 +929,23 @@ os_socket_set_ip_add_membership(bh_socket_t socket,
923929
mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4;
924930
mreq.imr_address.s_addr = imr_interface;
925931

926-
if (zsock_setsockopt(socket->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
927-
sizeof(mreq))
928-
!= 0) {
929-
return BHT_ERROR;
932+
int ret = zsock_setsockopt(socket->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
933+
&mreq, sizeof(mreq));
934+
if (ret != 0) {
935+
/* Treat certain errors as non-fatal for multicast membership.
936+
* These conditions indicate the operation is either already
937+
* complete or not supported by the network stack, but shouldn't
938+
* prevent the application from continuing. This improves
939+
* compatibility across different Zephyr network configurations. */
940+
switch (errno) {
941+
case EALREADY: /* already joined: OK */
942+
case EADDRINUSE: /* duplicate membership: OK */
943+
case ENOPROTOOPT: /* option not supported: treat as soft-OK */
944+
case ENOSYS: /* not implemented: soft-OK */
945+
return BHT_OK;
946+
default:
947+
return BHT_ERROR;
948+
}
930949
}
931950
}
932951
return BHT_OK;
@@ -964,10 +983,23 @@ os_socket_set_ip_drop_membership(bh_socket_t socket,
964983
mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4;
965984
mreq.imr_address.s_addr = imr_interface;
966985

967-
if (zsock_setsockopt(socket->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq,
968-
sizeof(mreq))
969-
!= 0) {
970-
return BHT_ERROR;
986+
int ret = zsock_setsockopt(socket->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
987+
&mreq, sizeof(mreq));
988+
if (ret != 0) {
989+
/* Treat certain errors as non-fatal for multicast membership.
990+
* These conditions indicate the operation is either already
991+
* complete or not supported by the network stack, but shouldn't
992+
* prevent the application from continuing. This improves
993+
* compatibility across different Zephyr network configurations. */
994+
switch (errno) {
995+
case EALREADY: /* already joined: OK */
996+
case EADDRINUSE: /* duplicate membership: OK */
997+
case ENOPROTOOPT: /* option not supported: treat as soft-OK */
998+
case ENOSYS: /* not implemented: soft-OK */
999+
return BHT_OK;
1000+
default:
1001+
return BHT_ERROR;
1002+
}
9711003
}
9721004
}
9731005
return BHT_OK;

0 commit comments

Comments
 (0)