From 35f972fc505010275338b5429a3a89a475de8451 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 22 Dec 2025 14:20:41 -0800 Subject: [PATCH] Format wasip2/wasip1-threads files as well Update CI to format a few more targets, then apply all the formatting. --- .github/workflows/main.yml | 4 + cmake/clang-format.cmake | 3 + libc-bottom-half/sources/bind.c | 19 +- libc-bottom-half/sources/connect.c | 19 +- libc-bottom-half/sources/descriptor_table.c | 111 +- libc-bottom-half/sources/getsockpeername.c | 38 +- libc-bottom-half/sources/listen.c | 33 +- libc-bottom-half/sources/netdb.c | 406 +++--- libc-bottom-half/sources/recv.c | 36 +- libc-bottom-half/sources/send.c | 34 +- libc-bottom-half/sources/shutdown.c | 16 +- libc-bottom-half/sources/socket.c | 100 +- libc-bottom-half/sources/sockets_utils.c | 641 +++++----- libc-bottom-half/sources/sockopt.c | 74 +- libc-bottom-half/sources/wasip2_file.c | 97 +- libc-bottom-half/sources/wasip2_file_utils.c | 22 +- libc-bottom-half/sources/wasip2_stdio.c | 58 +- libc-bottom-half/sources/wasip2_tcp.c | 1093 +++++++++-------- libc-bottom-half/sources/wasip2_udp.c | 734 +++++------ test/src/busywait.c | 22 +- test/src/poll-nonblocking-socket.c | 87 +- test/src/pthread_cond_busywait.c | 6 +- test/src/pthread_mutex_busywait.c | 6 +- test/src/pthread_tsd_busywait.c | 6 +- test/src/setsockopt.c | 122 +- test/src/sockets-client-handle-hangups.c | 90 +- .../src/sockets-client-hangup-after-connect.c | 52 +- .../src/sockets-client-hangup-after-sending.c | 62 +- .../sockets-client-hangup-while-receiving.c | 73 +- .../src/sockets-client-hangup-while-sending.c | 69 +- test/src/sockets-client-udp-blocking.c | 90 +- test/src/sockets-client.c | 76 +- test/src/sockets-multiple-client.c | 87 +- test/src/sockets-multiple-server.c | 134 +- test/src/sockets-nonblocking-multiple.c | 497 ++++---- test/src/sockets-nonblocking-udp-multiple.c | 374 +++--- test/src/sockets-nonblocking-udp.c | 202 +-- test/src/sockets-server-handle-hangups.c | 102 +- test/src/sockets-server-hangup-before-recv.c | 97 +- test/src/sockets-server-hangup-before-send.c | 86 +- test/src/sockets-server-hangup-during-recv.c | 94 +- test/src/sockets-server-hangup-during-send.c | 90 +- test/src/sockets-server-udp-blocking.c | 92 +- test/src/sockets-server.c | 90 +- 44 files changed, 3174 insertions(+), 3070 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 67410d37a..f053aa05d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -209,6 +209,10 @@ jobs: submodules: true - run: cmake -S . -B build -DBUILD_TESTS=ON -G Ninja -DCMAKE_C_COMPILER=clang - run: ninja -C build format-check + - run: cmake -S . -B build -DTARGET_TRIPLE=wasm32-wasip2 + - run: ninja -C build format-check + - run: cmake -S . -B build -DTARGET_TRIPLE=wasm32-wasip1-threads + - run: ninja -C build format-check rustfmt: name: Rustfmt diff --git a/cmake/clang-format.cmake b/cmake/clang-format.cmake index 38f5a7b40..52a5942cb 100644 --- a/cmake/clang-format.cmake +++ b/cmake/clang-format.cmake @@ -20,6 +20,9 @@ add_custom_target(format-check) set(formatted_sources) function(clang_format_file file) + if (file MATCHES "wasip2\..$") # Skip auto-generated files + return() + endif() cmake_path(ABSOLUTE_PATH file BASE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE src) # Only format sources primarily authored in this repository itself. This diff --git a/libc-bottom-half/sources/bind.c b/libc-bottom-half/sources/bind.c index 9062b90da..ce1b696bd 100644 --- a/libc-bottom-half/sources/bind.c +++ b/libc-bottom-half/sources/bind.c @@ -2,14 +2,13 @@ #include #include -int bind(int socket, const struct sockaddr *addr, socklen_t addrlen) -{ - descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); - if (!entry) - return -1; - if (!entry->vtable->bind) { - errno = EOPNOTSUPP; - return -1; - } - return entry->vtable->bind(entry->data, addr, addrlen); +int bind(int socket, const struct sockaddr *addr, socklen_t addrlen) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); + if (!entry) + return -1; + if (!entry->vtable->bind) { + errno = EOPNOTSUPP; + return -1; + } + return entry->vtable->bind(entry->data, addr, addrlen); } diff --git a/libc-bottom-half/sources/connect.c b/libc-bottom-half/sources/connect.c index 9dcd7ce77..4dcad58c8 100644 --- a/libc-bottom-half/sources/connect.c +++ b/libc-bottom-half/sources/connect.c @@ -2,14 +2,13 @@ #include #include -int connect(int fd, const struct sockaddr *addr, socklen_t addrlen) -{ - descriptor_table_entry_t *entry = descriptor_table_get_ref(fd); - if (!entry) - return -1; - if (!entry->vtable->connect) { - errno = EOPNOTSUPP; - return -1; - } - return entry->vtable->connect(entry->data, addr, addrlen); +int connect(int fd, const struct sockaddr *addr, socklen_t addrlen) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(fd); + if (!entry) + return -1; + if (!entry->vtable->connect) { + errno = EOPNOTSUPP; + return -1; + } + return entry->vtable->connect(entry->data, addr, addrlen); } diff --git a/libc-bottom-half/sources/descriptor_table.c b/libc-bottom-half/sources/descriptor_table.c index d1a141ef2..ecc31150b 100644 --- a/libc-bottom-half/sources/descriptor_table.c +++ b/libc-bottom-half/sources/descriptor_table.c @@ -10,31 +10,29 @@ #include #define MINSIZE 8 -#define MAXSIZE ((size_t)-1 / 2 + 1) +#define MAXSIZE ((size_t) - 1 / 2 + 1) typedef struct { - bool occupied; - union { - int next; - descriptor_table_entry_t entry; - }; + bool occupied; + union { + int next; + descriptor_table_entry_t entry; + }; } descriptor_table_item_t; typedef struct { - // Dynamically allocated array of `cap` entries. - descriptor_table_item_t *entries; - // Next free entry. - int next; - // Number of `entries` that are initialized. - size_t len; - // Dynamic length of `entries`. - size_t cap; + // Dynamically allocated array of `cap` entries. + descriptor_table_item_t *entries; + // Next free entry. + int next; + // Number of `entries` that are initialized. + size_t len; + // Dynamic length of `entries`. + size_t cap; } descriptor_table_t; -static descriptor_table_t global_table = { .entries = NULL, - .next = 0, - .len = 0, - .cap = 0 }; +static descriptor_table_t global_table = { + .entries = NULL, .next = 0, .len = 0, .cap = 0}; static int global_table_stdio_initialized = 0; /** @@ -106,7 +104,8 @@ static descriptor_table_entry_t *lookup(descriptor_table_t *table, int fd) { * * Returns -1 on failure and sets `errno`. */ -static int remove(descriptor_table_t *table, int fd, descriptor_table_entry_t *ret) { +static int remove(descriptor_table_t *table, int fd, + descriptor_table_entry_t *ret) { if (fd < 0 || (size_t)fd >= table->len) { errno = EBADF; return -1; @@ -133,51 +132,47 @@ static int init_stdio() { return __wasilibc_init_stdio(); } -int descriptor_table_insert(descriptor_table_entry_t entry) -{ - if (!stdio_initialized && init_stdio() < 0) - goto error; - int fd = allocate(&global_table, entry); - if (fd < 0) - goto error; - return fd; +int descriptor_table_insert(descriptor_table_entry_t entry) { + if (!stdio_initialized && init_stdio() < 0) + goto error; + int fd = allocate(&global_table, entry); + if (fd < 0) + goto error; + return fd; error: - entry.vtable->free(entry.data); - return -1; + entry.vtable->free(entry.data); + return -1; } -descriptor_table_entry_t *descriptor_table_get_ref(int fd) -{ - if (!stdio_initialized && init_stdio() < 0) - return NULL; - return lookup(&global_table, fd); +descriptor_table_entry_t *descriptor_table_get_ref(int fd) { + if (!stdio_initialized && init_stdio() < 0) + return NULL; + return lookup(&global_table, fd); } -int descriptor_table_renumber(int fd, int newfd) -{ - descriptor_table_entry_t* fdentry = descriptor_table_get_ref(fd); - if (!fdentry) - return -1; - descriptor_table_entry_t* newfdentry = descriptor_table_get_ref(newfd); - if (!newfdentry) - return -1; +int descriptor_table_renumber(int fd, int newfd) { + descriptor_table_entry_t *fdentry = descriptor_table_get_ref(fd); + if (!fdentry) + return -1; + descriptor_table_entry_t *newfdentry = descriptor_table_get_ref(newfd); + if (!newfdentry) + return -1; - descriptor_table_entry_t temp = *fdentry; - *fdentry = *newfdentry; - *newfdentry = temp; - if (remove(&global_table, fd, &temp) < 0) - return -1; - temp.vtable->free(temp.data); - return 0; + descriptor_table_entry_t temp = *fdentry; + *fdentry = *newfdentry; + *newfdentry = temp; + if (remove(&global_table, fd, &temp) < 0) + return -1; + temp.vtable->free(temp.data); + return 0; } -int descriptor_table_remove(int fd) -{ - if (!stdio_initialized && init_stdio() < 0) - return -1; - descriptor_table_entry_t entry; - if (remove(&global_table, fd, &entry) < 0) - return -1; - entry.vtable->free(entry.data); - return 0; +int descriptor_table_remove(int fd) { + if (!stdio_initialized && init_stdio() < 0) + return -1; + descriptor_table_entry_t entry; + if (remove(&global_table, fd, &entry) < 0) + return -1; + entry.vtable->free(entry.data); + return 0; } diff --git a/libc-bottom-half/sources/getsockpeername.c b/libc-bottom-half/sources/getsockpeername.c index 27ad2afb3..771806c97 100644 --- a/libc-bottom-half/sources/getsockpeername.c +++ b/libc-bottom-half/sources/getsockpeername.c @@ -3,27 +3,25 @@ #include int getsockname(int socket, struct sockaddr *__restrict addr, - socklen_t *__restrict addrlen) -{ - descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); - if (!entry) - return -1; - if (!entry->vtable->getsockname) { - errno = ENOTSOCK; - return -1; - } - return entry->vtable->getsockname(entry->data, addr, addrlen); + socklen_t *__restrict addrlen) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); + if (!entry) + return -1; + if (!entry->vtable->getsockname) { + errno = ENOTSOCK; + return -1; + } + return entry->vtable->getsockname(entry->data, addr, addrlen); } int getpeername(int socket, struct sockaddr *__restrict addr, - socklen_t *__restrict addrlen) -{ - descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); - if (!entry) - return -1; - if (!entry->vtable->getpeername) { - errno = ENOTSOCK; - return -1; - } - return entry->vtable->getpeername(entry->data, addr, addrlen); + socklen_t *__restrict addrlen) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); + if (!entry) + return -1; + if (!entry->vtable->getpeername) { + errno = ENOTSOCK; + return -1; + } + return entry->vtable->getpeername(entry->data, addr, addrlen); } diff --git a/libc-bottom-half/sources/listen.c b/libc-bottom-half/sources/listen.c index 1f5fd1cc4..b33264a83 100644 --- a/libc-bottom-half/sources/listen.c +++ b/libc-bottom-half/sources/listen.c @@ -2,22 +2,21 @@ #include #include -int listen(int socket, int backlog) -{ - descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); - if (!entry) - return -1; +int listen(int socket, int backlog) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); + if (!entry) + return -1; - if (backlog < 0) { - // POSIX: - // > If listen() is called with a backlog argument value that is - // > less than 0, the function behaves as if it had been called - // > with a backlog argument value of 0. - backlog = 0; - } - if (!entry->vtable->listen) { - errno = EOPNOTSUPP; - return -1; - } - return entry->vtable->listen(entry->data, backlog); + if (backlog < 0) { + // POSIX: + // > If listen() is called with a backlog argument value that is + // > less than 0, the function behaves as if it had been called + // > with a backlog argument value of 0. + backlog = 0; + } + if (!entry->vtable->listen) { + errno = EOPNOTSUPP; + return -1; + } + return entry->vtable->listen(entry->data, backlog); } diff --git a/libc-bottom-half/sources/netdb.c b/libc-bottom-half/sources/netdb.c index d4f3f5b3c..38e2708e4 100644 --- a/libc-bottom-half/sources/netdb.c +++ b/libc-bottom-half/sources/netdb.c @@ -1,195 +1,189 @@ -#include +#include #include +#include #include -#include #include #include _Thread_local int h_errno = 0; -static struct servent global_serv = { 0 }; - -static int map_error(ip_name_lookup_error_code_t error) -{ - switch (error) { - case NETWORK_ERROR_CODE_OUT_OF_MEMORY: - return EAI_MEMORY; - case NETWORK_ERROR_CODE_NAME_UNRESOLVABLE: - return EAI_NONAME; - case NETWORK_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE: - return EAI_AGAIN; - case NETWORK_ERROR_CODE_PERMANENT_RESOLVER_FAILURE: - return EAI_FAIL; - - default: - errno = __wasi_sockets_utils__map_error(error); - return EAI_SYSTEM; - } +static struct servent global_serv = {0}; + +static int map_error(ip_name_lookup_error_code_t error) { + switch (error) { + case NETWORK_ERROR_CODE_OUT_OF_MEMORY: + return EAI_MEMORY; + case NETWORK_ERROR_CODE_NAME_UNRESOLVABLE: + return EAI_NONAME; + case NETWORK_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE: + return EAI_AGAIN; + case NETWORK_ERROR_CODE_PERMANENT_RESOLVER_FAILURE: + return EAI_FAIL; + + default: + errno = __wasi_sockets_utils__map_error(error); + return EAI_SYSTEM; + } } -static int add_addr(ip_name_lookup_option_ip_address_t address, - in_port_t port, - int socktype, - const struct addrinfo *restrict hint, - struct addrinfo **restrict current, - struct addrinfo **restrict res) -{ - int family; - struct sockaddr *addr; - socklen_t addrlen; - switch (address.val.tag) { - case NETWORK_IP_ADDRESS_IPV4: { - if (hint && hint->ai_family != AF_UNSPEC && - hint->ai_family != AF_INET) { - return 0; - } - - network_ipv4_address_t ip = address.val.val.ipv4; - - family = PF_INET; - addrlen = sizeof(struct sockaddr_in); - addr = malloc(addrlen); - if (addr == NULL) { - freeaddrinfo(*res); - return EAI_MEMORY; - } - - struct sockaddr_in sockaddr = { - .sin_family = AF_INET, - .sin_port = port, - .sin_addr = { .s_addr = ip.f0 | (ip.f1 << 8) | - (ip.f2 << 16) | (ip.f3 << 24) }, - }; - memcpy(addr, &sockaddr, addrlen); - break; - } - case NETWORK_IP_ADDRESS_IPV6: { - if (hint && hint->ai_family != AF_UNSPEC && - hint->ai_family != AF_INET6) { - return 0; - } - - network_ipv6_address_t ip = address.val.val.ipv6; - - family = PF_INET6; - addrlen = sizeof(struct sockaddr_in6); - addr = malloc(addrlen); - if (addr == NULL) { - freeaddrinfo(*res); - return EAI_MEMORY; - } - - struct sockaddr_in6 sockaddr = { - .sin6_family = AF_INET6, - .sin6_port = port, - .sin6_addr = { - .s6_addr = { - ip.f0 >> 8, - ip.f0 & 0xFF, - ip.f1 >> 8, - ip.f1 & 0xFF, - ip.f2 >> 8, - ip.f2 & 0xFF, - ip.f3 >> 8, - ip.f3 & 0xFF, - ip.f4 >> 8, - ip.f4 & 0xFF, - ip.f5 >> 8, - ip.f5 & 0xFF, - ip.f6 >> 8, - ip.f6 & 0xFF, - ip.f7 >> 8, - ip.f7 & 0xFF, - } }, - .sin6_flowinfo = 0, - .sin6_scope_id = 0, - }; - memcpy(addr, &sockaddr, addrlen); - break; - } - default: /* unreachable */ - abort(); - } - - struct addrinfo *result = malloc(sizeof(struct addrinfo)); - if (result == NULL) { - freeaddrinfo(*res); - return EAI_MEMORY; - } - - *result = (struct addrinfo){ - .ai_family = family, - .ai_flags = 0, - .ai_socktype = socktype, - .ai_protocol = 0, - .ai_addrlen = addrlen, - .ai_addr = addr, - .ai_canonname = NULL, - .ai_next = NULL, - }; - - if (*current) { - (*current)->ai_next = result; - *current = result; - } else { - *current = result; - *res = result; - } - - return 0; +static int add_addr(ip_name_lookup_option_ip_address_t address, in_port_t port, + int socktype, const struct addrinfo *restrict hint, + struct addrinfo **restrict current, + struct addrinfo **restrict res) { + int family; + struct sockaddr *addr; + socklen_t addrlen; + switch (address.val.tag) { + case NETWORK_IP_ADDRESS_IPV4: { + if (hint && hint->ai_family != AF_UNSPEC && hint->ai_family != AF_INET) { + return 0; + } + + network_ipv4_address_t ip = address.val.val.ipv4; + + family = PF_INET; + addrlen = sizeof(struct sockaddr_in); + addr = malloc(addrlen); + if (addr == NULL) { + freeaddrinfo(*res); + return EAI_MEMORY; + } + + struct sockaddr_in sockaddr = { + .sin_family = AF_INET, + .sin_port = port, + .sin_addr = {.s_addr = + ip.f0 | (ip.f1 << 8) | (ip.f2 << 16) | (ip.f3 << 24)}, + }; + memcpy(addr, &sockaddr, addrlen); + break; + } + case NETWORK_IP_ADDRESS_IPV6: { + if (hint && hint->ai_family != AF_UNSPEC && hint->ai_family != AF_INET6) { + return 0; + } + + network_ipv6_address_t ip = address.val.val.ipv6; + + family = PF_INET6; + addrlen = sizeof(struct sockaddr_in6); + addr = malloc(addrlen); + if (addr == NULL) { + freeaddrinfo(*res); + return EAI_MEMORY; + } + + struct sockaddr_in6 sockaddr = { + .sin6_family = AF_INET6, + .sin6_port = port, + .sin6_addr = {.s6_addr = + { + ip.f0 >> 8, + ip.f0 & 0xFF, + ip.f1 >> 8, + ip.f1 & 0xFF, + ip.f2 >> 8, + ip.f2 & 0xFF, + ip.f3 >> 8, + ip.f3 & 0xFF, + ip.f4 >> 8, + ip.f4 & 0xFF, + ip.f5 >> 8, + ip.f5 & 0xFF, + ip.f6 >> 8, + ip.f6 & 0xFF, + ip.f7 >> 8, + ip.f7 & 0xFF, + }}, + .sin6_flowinfo = 0, + .sin6_scope_id = 0, + }; + memcpy(addr, &sockaddr, addrlen); + break; + } + default: /* unreachable */ + abort(); + } + + struct addrinfo *result = malloc(sizeof(struct addrinfo)); + if (result == NULL) { + freeaddrinfo(*res); + return EAI_MEMORY; + } + + *result = (struct addrinfo){ + .ai_family = family, + .ai_flags = 0, + .ai_socktype = socktype, + .ai_protocol = 0, + .ai_addrlen = addrlen, + .ai_addr = addr, + .ai_canonname = NULL, + .ai_next = NULL, + }; + + if (*current) { + (*current)->ai_next = result; + *current = result; + } else { + *current = result; + *res = result; + } + + return 0; } -static bool set_global_serv_entry(const service_entry_t *entry, const char *proto) { - if (!entry) { - return false; // Service not found - } - - global_serv.s_name = entry->s_name; - global_serv.s_port = htons(entry->port); - global_serv.s_aliases = NULL; - - // If proto is NULL then any protocol is matched - if ((!proto || strcmp(proto, "tcp") == 0) && entry->protocol & SERVICE_PROTOCOL_TCP) { - global_serv.s_proto = "tcp"; - } - else if ((!proto || strcmp(proto, "udp") == 0) && entry->protocol & SERVICE_PROTOCOL_UDP) { - global_serv.s_proto = "udp"; - } - else { - return false; // Protocol not supported - } - - return true; +static bool set_global_serv_entry(const service_entry_t *entry, + const char *proto) { + if (!entry) { + return false; // Service not found + } + + global_serv.s_name = entry->s_name; + global_serv.s_port = htons(entry->port); + global_serv.s_aliases = NULL; + + // If proto is NULL then any protocol is matched + if ((!proto || strcmp(proto, "tcp") == 0) && + entry->protocol & SERVICE_PROTOCOL_TCP) { + global_serv.s_proto = "tcp"; + } else if ((!proto || strcmp(proto, "udp") == 0) && + entry->protocol & SERVICE_PROTOCOL_UDP) { + global_serv.s_proto = "udp"; + } else { + return false; // Protocol not supported + } + + return true; } int getaddrinfo(const char *restrict host, const char *restrict serv, - const struct addrinfo *restrict hint, - struct addrinfo **restrict res) -{ + const struct addrinfo *restrict hint, + struct addrinfo **restrict res) { if (host == NULL) { host = "localhost"; } *res = NULL; struct addrinfo *current = NULL; - wasip2_string_t name = { .ptr = (uint8_t *)host, .len = strlen(host) }; + wasip2_string_t name = {.ptr = (uint8_t *)host, .len = strlen(host)}; ip_name_lookup_own_resolve_address_stream_t stream; ip_name_lookup_error_code_t error; - if (!ip_name_lookup_resolve_addresses( - __wasi_sockets_utils__borrow_network(), &name, &stream, - &error)) + if (!ip_name_lookup_resolve_addresses(__wasi_sockets_utils__borrow_network(), + &name, &stream, &error)) return map_error(error); int ret = 0; ip_name_lookup_borrow_resolve_address_stream_t stream_borrow = - ip_name_lookup_borrow_resolve_address_stream(stream); + ip_name_lookup_borrow_resolve_address_stream(stream); // The 'serv' parameter can be either a port number or a service name. int port = 0; uint16_t protocol = SERVICE_PROTOCOL_TCP; if (serv != NULL) { port = __wasi_sockets_utils__parse_port(serv); if (port < 0) { - const service_entry_t *service = __wasi_sockets_utils__get_service_entry_by_name(serv); + const service_entry_t *service = + __wasi_sockets_utils__get_service_entry_by_name(serv); if (service) { port = service->port; protocol = service->protocol; @@ -205,7 +199,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, while (ret == 0) { ip_name_lookup_option_ip_address_t address; if (!ip_name_lookup_method_resolve_address_stream_resolve_next_address( - stream_borrow, &address, &error)) { + stream_borrow, &address, &error)) { if (error != NETWORK_ERROR_CODE_WOULD_BLOCK) { freeaddrinfo(*res); ret = map_error(error); @@ -214,7 +208,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, if (pollable.__handle == 0) { pollable = ip_name_lookup_method_resolve_address_stream_subscribe( - stream_borrow); + stream_borrow); } poll_method_pollable_block(poll_borrow_pollable(pollable)); continue; @@ -222,14 +216,12 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, if (!address.is_some) break; if (protocol & SERVICE_PROTOCOL_TCP) { - ret = add_addr(address, htons(port), SOCK_STREAM, - hint, ¤t, res); + ret = add_addr(address, htons(port), SOCK_STREAM, hint, ¤t, res); if (ret) break; } if (protocol & SERVICE_PROTOCOL_UDP) { - ret = add_addr(address, htons(port), SOCK_DGRAM, - hint, ¤t, res); + ret = add_addr(address, htons(port), SOCK_DGRAM, hint, ¤t, res); if (ret) break; } @@ -241,63 +233,57 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, return ret; } -void freeaddrinfo(struct addrinfo *p) -{ - while (p) { - struct addrinfo *next = p->ai_next; - free(p->ai_addr); - free(p); - p = next; - } +void freeaddrinfo(struct addrinfo *p) { + while (p) { + struct addrinfo *next = p->ai_next; + free(p->ai_addr); + free(p); + p = next; + } } int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, - char *restrict host, socklen_t hostlen, char *restrict serv, - socklen_t servlen, int flags) -{ - // TODO wasi-sockets - errno = EOPNOTSUPP; - return EAI_SYSTEM; + char *restrict host, socklen_t hostlen, char *restrict serv, + socklen_t servlen, int flags) { + // TODO wasi-sockets + errno = EOPNOTSUPP; + return EAI_SYSTEM; } -struct hostent *gethostbyname(const char *name) -{ - // TODO wasi-sockets - return NULL; +struct hostent *gethostbyname(const char *name) { + // TODO wasi-sockets + return NULL; } -struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) -{ - // TODO wasi-sockets - return NULL; +struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) { + // TODO wasi-sockets + return NULL; } -const char *hstrerror(int err) -{ - // TODO wasi-sockets - return "hstrerror: TODO"; +const char *hstrerror(int err) { + // TODO wasi-sockets + return "hstrerror: TODO"; } -struct servent *getservbyname(const char *name, const char *proto) -{ - const service_entry_t *entry = __wasi_sockets_utils__get_service_entry_by_name(name); - if (!set_global_serv_entry(entry, proto)) { - return NULL; - } - return &global_serv; +struct servent *getservbyname(const char *name, const char *proto) { + const service_entry_t *entry = + __wasi_sockets_utils__get_service_entry_by_name(name); + if (!set_global_serv_entry(entry, proto)) { + return NULL; + } + return &global_serv; } -struct servent *getservbyport(int port, const char *proto) -{ - const service_entry_t *entry = __wasi_sockets_utils__get_service_entry_by_port(htons(port)); - if (!set_global_serv_entry(entry, proto)) { - return NULL; - } - return &global_serv; +struct servent *getservbyport(int port, const char *proto) { + const service_entry_t *entry = + __wasi_sockets_utils__get_service_entry_by_port(htons(port)); + if (!set_global_serv_entry(entry, proto)) { + return NULL; + } + return &global_serv; } -struct protoent *getprotobyname(const char *name) -{ - // TODO wasi-sockets - return NULL; +struct protoent *getprotobyname(const char *name) { + // TODO wasi-sockets + return NULL; } diff --git a/libc-bottom-half/sources/recv.c b/libc-bottom-half/sources/recv.c index 2a000ac65..16f58cf33 100644 --- a/libc-bottom-half/sources/recv.c +++ b/libc-bottom-half/sources/recv.c @@ -2,27 +2,25 @@ #include #include -ssize_t recv(int socket, void *restrict buffer, size_t length, int flags) -{ - return recvfrom(socket, buffer, length, flags, NULL, NULL); +ssize_t recv(int socket, void *restrict buffer, size_t length, int flags) { + return recvfrom(socket, buffer, length, flags, NULL, NULL); } ssize_t recvfrom(int socket, void *__restrict buffer, size_t length, int flags, - struct sockaddr *__restrict addr, - socklen_t *__restrict addrlen) -{ - descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); - if (!entry) - return -1; + struct sockaddr *__restrict addr, + socklen_t *__restrict addrlen) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); + if (!entry) + return -1; - if (buffer == NULL) { - errno = EINVAL; - return -1; - } - if (entry->vtable->recvfrom == NULL) { - errno = EOPNOTSUPP; - return -1; - } - return entry->vtable->recvfrom(entry->data, buffer, length, flags, - addr, addrlen); + if (buffer == NULL) { + errno = EINVAL; + return -1; + } + if (entry->vtable->recvfrom == NULL) { + errno = EOPNOTSUPP; + return -1; + } + return entry->vtable->recvfrom(entry->data, buffer, length, flags, addr, + addrlen); } diff --git a/libc-bottom-half/sources/send.c b/libc-bottom-half/sources/send.c index 01dc6bef9..834ef67ca 100644 --- a/libc-bottom-half/sources/send.c +++ b/libc-bottom-half/sources/send.c @@ -2,27 +2,25 @@ #include #include -ssize_t send(int socket, const void *buffer, size_t length, int flags) -{ - return sendto(socket, buffer, length, flags, NULL, 0); +ssize_t send(int socket, const void *buffer, size_t length, int flags) { + return sendto(socket, buffer, length, flags, NULL, 0); } ssize_t sendto(int socket, const void *buffer, size_t length, int flags, - const struct sockaddr *addr, socklen_t addrlen) -{ - descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); - if (!entry) - return -1; + const struct sockaddr *addr, socklen_t addrlen) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); + if (!entry) + return -1; - if (buffer == NULL) { - errno = EINVAL; - return -1; - } + if (buffer == NULL) { + errno = EINVAL; + return -1; + } - if (entry->vtable->sendto == NULL) { - errno = EOPNOTSUPP; - return -1; - } - return entry->vtable->sendto(entry->data, buffer, length, flags, - addr, addrlen); + if (entry->vtable->sendto == NULL) { + errno = EOPNOTSUPP; + return -1; + } + return entry->vtable->sendto(entry->data, buffer, length, flags, addr, + addrlen); } diff --git a/libc-bottom-half/sources/shutdown.c b/libc-bottom-half/sources/shutdown.c index e6a7094b6..735cc2b7f 100644 --- a/libc-bottom-half/sources/shutdown.c +++ b/libc-bottom-half/sources/shutdown.c @@ -2,12 +2,12 @@ #include int shutdown(int socket, int how) { - descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); - if (!entry) - return -1; - if (entry->vtable->shutdown == NULL) { - errno = EOPNOTSUPP; - return -1; - } - return entry->vtable->shutdown(entry->data, how); + descriptor_table_entry_t *entry = descriptor_table_get_ref(socket); + if (!entry) + return -1; + if (entry->vtable->shutdown == NULL) { + errno = EOPNOTSUPP; + return -1; + } + return entry->vtable->shutdown(entry->data, how); } diff --git a/libc-bottom-half/sources/socket.c b/libc-bottom-half/sources/socket.c index 265ff4871..2658f8bc1 100644 --- a/libc-bottom-half/sources/socket.c +++ b/libc-bottom-half/sources/socket.c @@ -5,61 +5,57 @@ #include #include -static int tcp_socket(network_ip_address_family_t family, bool blocking) -{ - tcp_create_socket_error_code_t error; - tcp_own_tcp_socket_t socket; - if (!tcp_create_socket_create_tcp_socket(family, &socket, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return __wasilibc_add_tcp_socket(socket, family, blocking); +static int tcp_socket(network_ip_address_family_t family, bool blocking) { + tcp_create_socket_error_code_t error; + tcp_own_tcp_socket_t socket; + if (!tcp_create_socket_create_tcp_socket(family, &socket, &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + return __wasilibc_add_tcp_socket(socket, family, blocking); } -static int udp_socket(network_ip_address_family_t family, bool blocking) -{ - udp_create_socket_error_code_t error; - udp_own_udp_socket_t socket; - if (!udp_create_socket_create_udp_socket(family, &socket, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } +static int udp_socket(network_ip_address_family_t family, bool blocking) { + udp_create_socket_error_code_t error; + udp_own_udp_socket_t socket; + if (!udp_create_socket_create_udp_socket(family, &socket, &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } - return __wasilibc_add_udp_socket(socket, family, blocking); + return __wasilibc_add_udp_socket(socket, family, blocking); } -int socket(int domain, int type, int protocol) -{ - network_ip_address_family_t family; - switch (domain) { - case PF_INET: - family = NETWORK_IP_ADDRESS_FAMILY_IPV4; - break; - - case PF_INET6: - family = NETWORK_IP_ADDRESS_FAMILY_IPV6; - break; - - default: - errno = EAFNOSUPPORT; - return -1; - } - - int real_type = type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC); - bool blocking = (type & SOCK_NONBLOCK) == 0; - // Ignore SOCK_CLOEXEC flag. That concept does not exist in WASI. - - if (real_type == SOCK_STREAM && - (protocol == 0 || protocol == IPPROTO_TCP)) { - return tcp_socket(family, blocking); - - } else if (real_type == SOCK_DGRAM && - (protocol == 0 || protocol == IPPROTO_UDP)) { - return udp_socket(family, blocking); - - } else { - errno = EPROTONOSUPPORT; - return -1; - } +int socket(int domain, int type, int protocol) { + network_ip_address_family_t family; + switch (domain) { + case PF_INET: + family = NETWORK_IP_ADDRESS_FAMILY_IPV4; + break; + + case PF_INET6: + family = NETWORK_IP_ADDRESS_FAMILY_IPV6; + break; + + default: + errno = EAFNOSUPPORT; + return -1; + } + + int real_type = type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC); + bool blocking = (type & SOCK_NONBLOCK) == 0; + // Ignore SOCK_CLOEXEC flag. That concept does not exist in WASI. + + if (real_type == SOCK_STREAM && (protocol == 0 || protocol == IPPROTO_TCP)) { + return tcp_socket(family, blocking); + + } else if (real_type == SOCK_DGRAM && + (protocol == 0 || protocol == IPPROTO_UDP)) { + return udp_socket(family, blocking); + + } else { + errno = EPROTONOSUPPORT; + return -1; + } } diff --git a/libc-bottom-half/sources/sockets_utils.c b/libc-bottom-half/sources/sockets_utils.c index 482c3b05f..5fe96dd54 100644 --- a/libc-bottom-half/sources/sockets_utils.c +++ b/libc-bottom-half/sources/sockets_utils.c @@ -1,6 +1,6 @@ +#include #include #include -#include #include #include @@ -8,362 +8,347 @@ static network_own_network_t global_network; static bool global_network_initialized = false; static const service_entry_t global_services[] = { - { "domain", 53, SERVICE_PROTOCOL_TCP | SERVICE_PROTOCOL_UDP }, - { "ftp", 21, SERVICE_PROTOCOL_TCP }, - { "ftp-data", 20, SERVICE_PROTOCOL_TCP }, - { "ftps", 990, SERVICE_PROTOCOL_TCP }, - { "ftps-data", 989, SERVICE_PROTOCOL_TCP }, - { "http", 80, SERVICE_PROTOCOL_TCP | SERVICE_PROTOCOL_UDP }, - { "https", 443, SERVICE_PROTOCOL_TCP | SERVICE_PROTOCOL_UDP }, - { "imap", 143, SERVICE_PROTOCOL_TCP }, - { "imaps", 993, SERVICE_PROTOCOL_TCP }, - { "ntp", 123, SERVICE_PROTOCOL_TCP }, - { "pop3", 110, SERVICE_PROTOCOL_TCP }, - { "pop3s", 995, SERVICE_PROTOCOL_TCP }, - { "smtp", 25, SERVICE_PROTOCOL_TCP }, - { "ssh", 22, SERVICE_PROTOCOL_TCP }, - { "submission", 587, SERVICE_PROTOCOL_TCP }, - { "submissions", 465, SERVICE_PROTOCOL_TCP }, - { "telnet", 23, SERVICE_PROTOCOL_TCP }, - { 0 }, + {"domain", 53, SERVICE_PROTOCOL_TCP | SERVICE_PROTOCOL_UDP}, + {"ftp", 21, SERVICE_PROTOCOL_TCP}, + {"ftp-data", 20, SERVICE_PROTOCOL_TCP}, + {"ftps", 990, SERVICE_PROTOCOL_TCP}, + {"ftps-data", 989, SERVICE_PROTOCOL_TCP}, + {"http", 80, SERVICE_PROTOCOL_TCP | SERVICE_PROTOCOL_UDP}, + {"https", 443, SERVICE_PROTOCOL_TCP | SERVICE_PROTOCOL_UDP}, + {"imap", 143, SERVICE_PROTOCOL_TCP}, + {"imaps", 993, SERVICE_PROTOCOL_TCP}, + {"ntp", 123, SERVICE_PROTOCOL_TCP}, + {"pop3", 110, SERVICE_PROTOCOL_TCP}, + {"pop3s", 995, SERVICE_PROTOCOL_TCP}, + {"smtp", 25, SERVICE_PROTOCOL_TCP}, + {"ssh", 22, SERVICE_PROTOCOL_TCP}, + {"submission", 587, SERVICE_PROTOCOL_TCP}, + {"submissions", 465, SERVICE_PROTOCOL_TCP}, + {"telnet", 23, SERVICE_PROTOCOL_TCP}, + {0}, }; weak_alias(global_services, __wasi_sockets_services_db); -network_borrow_network_t __wasi_sockets_utils__borrow_network() -{ - if (!global_network_initialized) { - global_network = instance_network_instance_network(); - global_network_initialized = true; - } +network_borrow_network_t __wasi_sockets_utils__borrow_network() { + if (!global_network_initialized) { + global_network = instance_network_instance_network(); + global_network_initialized = true; + } - return network_borrow_network(global_network); + return network_borrow_network(global_network); } -int __wasi_sockets_utils__map_error(network_error_code_t wasi_error) -{ - switch (wasi_error) { - case NETWORK_ERROR_CODE_ACCESS_DENIED: - return EACCES; - case NETWORK_ERROR_CODE_NOT_SUPPORTED: - return EOPNOTSUPP; - case NETWORK_ERROR_CODE_INVALID_ARGUMENT: - return EINVAL; - case NETWORK_ERROR_CODE_OUT_OF_MEMORY: - return ENOMEM; - case NETWORK_ERROR_CODE_TIMEOUT: - return ETIMEDOUT; - case NETWORK_ERROR_CODE_CONCURRENCY_CONFLICT: - return EALREADY; - case NETWORK_ERROR_CODE_WOULD_BLOCK: - return EWOULDBLOCK; - case NETWORK_ERROR_CODE_NEW_SOCKET_LIMIT: - return EMFILE; - case NETWORK_ERROR_CODE_ADDRESS_NOT_BINDABLE: - return EADDRNOTAVAIL; - case NETWORK_ERROR_CODE_ADDRESS_IN_USE: - return EADDRINUSE; - case NETWORK_ERROR_CODE_REMOTE_UNREACHABLE: - return EHOSTUNREACH; - case NETWORK_ERROR_CODE_CONNECTION_REFUSED: - return ECONNREFUSED; - case NETWORK_ERROR_CODE_CONNECTION_RESET: - return ECONNRESET; - case NETWORK_ERROR_CODE_CONNECTION_ABORTED: - return ECONNABORTED; - case NETWORK_ERROR_CODE_DATAGRAM_TOO_LARGE: - return EMSGSIZE; - - case NETWORK_ERROR_CODE_INVALID_STATE: - case NETWORK_ERROR_CODE_NOT_IN_PROGRESS: - abort(); // If our internal state checks are working right, these errors should never show up. - break; - - case NETWORK_ERROR_CODE_NAME_UNRESOLVABLE: - case NETWORK_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE: - case NETWORK_ERROR_CODE_PERMANENT_RESOLVER_FAILURE: - abort(); // These errors are specific to getaddrinfo, which should have filtered these errors out before calling this generic method - break; - - case NETWORK_ERROR_CODE_UNKNOWN: - default: - return EOPNOTSUPP; - } +int __wasi_sockets_utils__map_error(network_error_code_t wasi_error) { + switch (wasi_error) { + case NETWORK_ERROR_CODE_ACCESS_DENIED: + return EACCES; + case NETWORK_ERROR_CODE_NOT_SUPPORTED: + return EOPNOTSUPP; + case NETWORK_ERROR_CODE_INVALID_ARGUMENT: + return EINVAL; + case NETWORK_ERROR_CODE_OUT_OF_MEMORY: + return ENOMEM; + case NETWORK_ERROR_CODE_TIMEOUT: + return ETIMEDOUT; + case NETWORK_ERROR_CODE_CONCURRENCY_CONFLICT: + return EALREADY; + case NETWORK_ERROR_CODE_WOULD_BLOCK: + return EWOULDBLOCK; + case NETWORK_ERROR_CODE_NEW_SOCKET_LIMIT: + return EMFILE; + case NETWORK_ERROR_CODE_ADDRESS_NOT_BINDABLE: + return EADDRNOTAVAIL; + case NETWORK_ERROR_CODE_ADDRESS_IN_USE: + return EADDRINUSE; + case NETWORK_ERROR_CODE_REMOTE_UNREACHABLE: + return EHOSTUNREACH; + case NETWORK_ERROR_CODE_CONNECTION_REFUSED: + return ECONNREFUSED; + case NETWORK_ERROR_CODE_CONNECTION_RESET: + return ECONNRESET; + case NETWORK_ERROR_CODE_CONNECTION_ABORTED: + return ECONNABORTED; + case NETWORK_ERROR_CODE_DATAGRAM_TOO_LARGE: + return EMSGSIZE; + + case NETWORK_ERROR_CODE_INVALID_STATE: + case NETWORK_ERROR_CODE_NOT_IN_PROGRESS: + abort(); // If our internal state checks are working right, these errors + // should never show up. + break; + + case NETWORK_ERROR_CODE_NAME_UNRESOLVABLE: + case NETWORK_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE: + case NETWORK_ERROR_CODE_PERMANENT_RESOLVER_FAILURE: + abort(); // These errors are specific to getaddrinfo, which should have + // filtered these errors out before calling this generic method + break; + + case NETWORK_ERROR_CODE_UNKNOWN: + default: + return EOPNOTSUPP; + } } bool __wasi_sockets_utils__parse_address( - network_ip_address_family_t expected_family, - const struct sockaddr *address, socklen_t len, - network_ip_socket_address_t *result, int *error) -{ - if (address == NULL || len < sizeof(struct sockaddr)) { - *error = EINVAL; - return false; - } - - switch (expected_family) { - case NETWORK_IP_ADDRESS_FAMILY_IPV4: { - if (address->sa_family != AF_INET) { - *error = EAFNOSUPPORT; - return false; - } - - if (len < sizeof(struct sockaddr_in)) { - *error = EINVAL; - return false; - } - - struct sockaddr_in *ipv4 = (struct sockaddr_in *)address; - unsigned ip = ipv4->sin_addr.s_addr; - unsigned short port = ipv4->sin_port; - *result = (network_ip_socket_address_t){ - .tag = NETWORK_IP_SOCKET_ADDRESS_IPV4, - .val = { .ipv4 = { - .port = ntohs(port), // (port << 8) | (port >> 8), - .address = { ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24 }, - } }, - }; - return true; - } - case NETWORK_IP_ADDRESS_FAMILY_IPV6: { - if (address->sa_family != AF_INET6) { - *error = EAFNOSUPPORT; - return false; - } - - if (len < sizeof(struct sockaddr_in6)) { - *error = EINVAL; - return false; - } - - struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)address; - unsigned char *ip = (unsigned char *)&(ipv6->sin6_addr.s6_addr); - unsigned short port = ipv6->sin6_port; - *result = (network_ip_socket_address_t){ - .tag = NETWORK_IP_SOCKET_ADDRESS_IPV6, - .val = { .ipv6 = { - .port = ntohs(port), - .address = { - (((unsigned short)ip[0]) << 8) | ip[1], - (((unsigned short)ip[2]) << 8) | ip[3], - (((unsigned short)ip[4]) << 8) | ip[5], - (((unsigned short)ip[6]) << 8) | ip[7], - (((unsigned short)ip[8]) << 8) | ip[9], - (((unsigned short)ip[10]) << 8) | ip[11], - (((unsigned short)ip[12]) << 8) | ip[13], - (((unsigned short)ip[14]) << 8) | ip[15], - }, - // TODO wasi-sockets: do these need to be endian-reversed? - .flow_info = ipv6->sin6_flowinfo, - .scope_id = ipv6->sin6_scope_id, - } } - }; - return true; - } - default: /* unreachable */ - abort(); - } + network_ip_address_family_t expected_family, const struct sockaddr *address, + socklen_t len, network_ip_socket_address_t *result, int *error) { + if (address == NULL || len < sizeof(struct sockaddr)) { + *error = EINVAL; + return false; + } + + switch (expected_family) { + case NETWORK_IP_ADDRESS_FAMILY_IPV4: { + if (address->sa_family != AF_INET) { + *error = EAFNOSUPPORT; + return false; + } + + if (len < sizeof(struct sockaddr_in)) { + *error = EINVAL; + return false; + } + + struct sockaddr_in *ipv4 = (struct sockaddr_in *)address; + unsigned ip = ipv4->sin_addr.s_addr; + unsigned short port = ipv4->sin_port; + *result = (network_ip_socket_address_t){ + .tag = NETWORK_IP_SOCKET_ADDRESS_IPV4, + .val = {.ipv4 = + { + .port = ntohs(port), // (port << 8) | (port >> 8), + .address = {ip & 0xFF, (ip >> 8) & 0xFF, + (ip >> 16) & 0xFF, ip >> 24}, + }}, + }; + return true; + } + case NETWORK_IP_ADDRESS_FAMILY_IPV6: { + if (address->sa_family != AF_INET6) { + *error = EAFNOSUPPORT; + return false; + } + + if (len < sizeof(struct sockaddr_in6)) { + *error = EINVAL; + return false; + } + + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)address; + unsigned char *ip = (unsigned char *)&(ipv6->sin6_addr.s6_addr); + unsigned short port = ipv6->sin6_port; + *result = (network_ip_socket_address_t){ + .tag = NETWORK_IP_SOCKET_ADDRESS_IPV6, + .val = {.ipv6 = { + .port = ntohs(port), + .address = + { + (((unsigned short)ip[0]) << 8) | ip[1], + (((unsigned short)ip[2]) << 8) | ip[3], + (((unsigned short)ip[4]) << 8) | ip[5], + (((unsigned short)ip[6]) << 8) | ip[7], + (((unsigned short)ip[8]) << 8) | ip[9], + (((unsigned short)ip[10]) << 8) | ip[11], + (((unsigned short)ip[12]) << 8) | ip[13], + (((unsigned short)ip[14]) << 8) | ip[15], + }, + // TODO wasi-sockets: do these need to be endian-reversed? + .flow_info = ipv6->sin6_flowinfo, + .scope_id = ipv6->sin6_scope_id, + }}}; + return true; + } + default: /* unreachable */ + abort(); + } } bool __wasi_sockets_utils__output_addr_validate( - network_ip_address_family_t expected_family, struct sockaddr *addr, - socklen_t *addrlen, output_sockaddr_t *result) -{ - // The address parameters must be either both null or both _not_ null. - - if (addr == NULL && addrlen == NULL) { - *result = (output_sockaddr_t){ .tag = OUTPUT_SOCKADDR_NULL, - .null = {} }; - return true; - - } else if (addr != NULL && addrlen != NULL) { - if (expected_family == NETWORK_IP_ADDRESS_FAMILY_IPV4) { - if (*addrlen < sizeof(struct sockaddr_in)) { - return false; - } - - *result = - (output_sockaddr_t){ .tag = OUTPUT_SOCKADDR_V4, - .v4 = { - .addr = (struct sockaddr_in - *) - addr, - .addrlen = addrlen, - } }; - return true; - - } else if (expected_family == NETWORK_IP_ADDRESS_FAMILY_IPV6) { - if (*addrlen < sizeof(struct sockaddr_in6)) { - return false; - } - - *result = - (output_sockaddr_t){ .tag = OUTPUT_SOCKADDR_V6, - .v6 = { - .addr = (struct sockaddr_in6 - *) - addr, - .addrlen = addrlen, - } }; - return true; - - } else { - abort(); - } - - } else { - return false; - } + network_ip_address_family_t expected_family, struct sockaddr *addr, + socklen_t *addrlen, output_sockaddr_t *result) { + // The address parameters must be either both null or both _not_ null. + + if (addr == NULL && addrlen == NULL) { + *result = (output_sockaddr_t){.tag = OUTPUT_SOCKADDR_NULL, .null = {}}; + return true; + + } else if (addr != NULL && addrlen != NULL) { + if (expected_family == NETWORK_IP_ADDRESS_FAMILY_IPV4) { + if (*addrlen < sizeof(struct sockaddr_in)) { + return false; + } + + *result = (output_sockaddr_t){.tag = OUTPUT_SOCKADDR_V4, + .v4 = { + .addr = (struct sockaddr_in *)addr, + .addrlen = addrlen, + }}; + return true; + + } else if (expected_family == NETWORK_IP_ADDRESS_FAMILY_IPV6) { + if (*addrlen < sizeof(struct sockaddr_in6)) { + return false; + } + + *result = (output_sockaddr_t){.tag = OUTPUT_SOCKADDR_V6, + .v6 = { + .addr = (struct sockaddr_in6 *)addr, + .addrlen = addrlen, + }}; + return true; + + } else { + abort(); + } + + } else { + return false; + } } void __wasi_sockets_utils__output_addr_write( - const network_ip_socket_address_t input, output_sockaddr_t *output) -{ - switch (input.tag) { - case NETWORK_IP_SOCKET_ADDRESS_IPV4: { - if (output->tag != OUTPUT_SOCKADDR_V4) { - abort(); - } - - network_ipv4_socket_address_t input_v4 = input.val.ipv4; - network_ipv4_address_t ip = input_v4.address; - - *output->v4.addrlen = sizeof(struct sockaddr_in); - *output->v4.addr = (struct sockaddr_in){ - .sin_family = AF_INET, - .sin_port = htons(input_v4.port), - .sin_addr = { .s_addr = ip.f0 | (ip.f1 << 8) | - (ip.f2 << 16) | (ip.f3 << 24) }, - }; - return; - } - case NETWORK_IP_SOCKET_ADDRESS_IPV6: { - if (output->tag != OUTPUT_SOCKADDR_V6) { - abort(); - } - - network_ipv6_socket_address_t input_v6 = input.val.ipv6; - network_ipv6_address_t ip = input_v6.address; - - *output->v6.addrlen = sizeof(struct sockaddr_in6); - *output->v6.addr = (struct sockaddr_in6) { - .sin6_family = AF_INET6, - .sin6_port = htons(input_v6.port), - .sin6_addr = { .s6_addr = { - ip.f0 >> 8, ip.f0 & 0xFF, - ip.f1 >> 8, ip.f1 & 0xFF, - ip.f2 >> 8, ip.f2 & 0xFF, - ip.f3 >> 8, ip.f3 & 0xFF, - ip.f4 >> 8, ip.f4 & 0xFF, - ip.f5 >> 8, ip.f5 & 0xFF, - ip.f6 >> 8, ip.f6 & 0xFF, - ip.f7 >> 8, ip.f7 & 0xFF, - } }, - // TODO wasi-sockets: do these need to be endian-reversed? - .sin6_flowinfo = input_v6.flow_info, - .sin6_scope_id = input_v6.scope_id, - }; - return; - } - default: /* unreachable */ - abort(); - } + const network_ip_socket_address_t input, output_sockaddr_t *output) { + switch (input.tag) { + case NETWORK_IP_SOCKET_ADDRESS_IPV4: { + if (output->tag != OUTPUT_SOCKADDR_V4) { + abort(); + } + + network_ipv4_socket_address_t input_v4 = input.val.ipv4; + network_ipv4_address_t ip = input_v4.address; + + *output->v4.addrlen = sizeof(struct sockaddr_in); + *output->v4.addr = (struct sockaddr_in){ + .sin_family = AF_INET, + .sin_port = htons(input_v4.port), + .sin_addr = {.s_addr = + ip.f0 | (ip.f1 << 8) | (ip.f2 << 16) | (ip.f3 << 24)}, + }; + return; + } + case NETWORK_IP_SOCKET_ADDRESS_IPV6: { + if (output->tag != OUTPUT_SOCKADDR_V6) { + abort(); + } + + network_ipv6_socket_address_t input_v6 = input.val.ipv6; + network_ipv6_address_t ip = input_v6.address; + + *output->v6.addrlen = sizeof(struct sockaddr_in6); + *output->v6.addr = (struct sockaddr_in6){ + .sin6_family = AF_INET6, + .sin6_port = htons(input_v6.port), + .sin6_addr = {.s6_addr = + { + ip.f0 >> 8, + ip.f0 & 0xFF, + ip.f1 >> 8, + ip.f1 & 0xFF, + ip.f2 >> 8, + ip.f2 & 0xFF, + ip.f3 >> 8, + ip.f3 & 0xFF, + ip.f4 >> 8, + ip.f4 & 0xFF, + ip.f5 >> 8, + ip.f5 & 0xFF, + ip.f6 >> 8, + ip.f6 & 0xFF, + ip.f7 >> 8, + ip.f7 & 0xFF, + }}, + // TODO wasi-sockets: do these need to be endian-reversed? + .sin6_flowinfo = input_v6.flow_info, + .sin6_scope_id = input_v6.scope_id, + }; + return; + } + default: /* unreachable */ + abort(); + } } -int __wasi_sockets_utils__posix_family(network_ip_address_family_t wasi_family) -{ - switch (wasi_family) { - case NETWORK_IP_ADDRESS_FAMILY_IPV4: - return AF_INET; - case NETWORK_IP_ADDRESS_FAMILY_IPV6: - return AF_INET6; - default: /* unreachable */ - abort(); - } +int __wasi_sockets_utils__posix_family( + network_ip_address_family_t wasi_family) { + switch (wasi_family) { + case NETWORK_IP_ADDRESS_FAMILY_IPV4: + return AF_INET; + case NETWORK_IP_ADDRESS_FAMILY_IPV6: + return AF_INET6; + default: /* unreachable */ + abort(); + } } network_ip_socket_address_t -__wasi_sockets_utils__any_addr(network_ip_address_family_t family) -{ - switch (family) { - case NETWORK_IP_ADDRESS_FAMILY_IPV4: - return (network_ip_socket_address_t){ .tag = NETWORK_IP_SOCKET_ADDRESS_IPV4, - .val = { - .ipv4 = { - .port = 0, - .address = { 0, - 0, - 0, - 0 }, - } } }; - case NETWORK_IP_ADDRESS_FAMILY_IPV6: - return (network_ip_socket_address_t){ .tag = NETWORK_IP_SOCKET_ADDRESS_IPV6, - .val = { - .ipv6 = { - .port = 0, - .address = { 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 }, - .flow_info = - 0, - .scope_id = - 0, - } } }; - default: /* unreachable */ - abort(); - } +__wasi_sockets_utils__any_addr(network_ip_address_family_t family) { + switch (family) { + case NETWORK_IP_ADDRESS_FAMILY_IPV4: + return (network_ip_socket_address_t){.tag = NETWORK_IP_SOCKET_ADDRESS_IPV4, + .val = {.ipv4 = { + .port = 0, + .address = {0, 0, 0, 0}, + }}}; + case NETWORK_IP_ADDRESS_FAMILY_IPV6: + return (network_ip_socket_address_t){ + .tag = NETWORK_IP_SOCKET_ADDRESS_IPV6, + .val = {.ipv6 = { + .port = 0, + .address = {0, 0, 0, 0, 0, 0, 0, 0}, + .flow_info = 0, + .scope_id = 0, + }}}; + default: /* unreachable */ + abort(); + } } -int __wasi_sockets_utils__parse_port(const char *restrict port_str) -{ - char *end = NULL; - errno = 0; - long port = strtol(port_str, &end, 10); - - // Check for various possible errors: - // - the input is not a valid number - // - the entire input string is not consumed - // - the number is not within the valid port range - // - the input does not start with a digit (strtol allows leading - // whitespace and optional sign) - if (errno != 0 || end == NULL || *end != '\0' || port < 0 - || port > 65535 || !isdigit(*port_str)) { - return -1; - } - - return (int)port; +int __wasi_sockets_utils__parse_port(const char *restrict port_str) { + char *end = NULL; + errno = 0; + long port = strtol(port_str, &end, 10); + + // Check for various possible errors: + // - the input is not a valid number + // - the entire input string is not consumed + // - the number is not within the valid port range + // - the input does not start with a digit (strtol allows leading + // whitespace and optional sign) + if (errno != 0 || end == NULL || *end != '\0' || port < 0 || port > 65535 || + !isdigit(*port_str)) { + return -1; + } + + return (int)port; } -const service_entry_t *__wasi_sockets_utils__get_service_entry_by_name(const char *name) -{ - if (!name) { - return NULL; - } +const service_entry_t * +__wasi_sockets_utils__get_service_entry_by_name(const char *name) { + if (!name) { + return NULL; + } - const service_entry_t *entry = __wasi_sockets_services_db; - while(entry->s_name) { - if (strcmp(name, entry->s_name) == 0) { - return entry; - } - ++entry; + const service_entry_t *entry = __wasi_sockets_services_db; + while (entry->s_name) { + if (strcmp(name, entry->s_name) == 0) { + return entry; } + ++entry; + } - return NULL; + return NULL; } -const service_entry_t *__wasi_sockets_utils__get_service_entry_by_port(const uint16_t port) -{ - const service_entry_t *entry = __wasi_sockets_services_db; - while(entry->s_name) { - if (entry->port == port) { - return entry; - } - ++entry; +const service_entry_t * +__wasi_sockets_utils__get_service_entry_by_port(const uint16_t port) { + const service_entry_t *entry = __wasi_sockets_services_db; + while (entry->s_name) { + if (entry->port == port) { + return entry; } + ++entry; + } - return NULL; + return NULL; } diff --git a/libc-bottom-half/sources/sockopt.c b/libc-bottom-half/sources/sockopt.c index 9039e0011..1673889d9 100644 --- a/libc-bottom-half/sources/sockopt.c +++ b/libc-bottom-half/sources/sockopt.c @@ -1,45 +1,45 @@ -#include #include +#include #include int getsockopt(int sockfd, int level, int optname, void *restrict optval, - socklen_t *restrict optlen) -{ - descriptor_table_entry_t *entry = descriptor_table_get_ref(sockfd); - if (!entry) - return -1; - - if (optval == NULL || optlen == NULL || *optlen < sizeof(int)) { - // FYI, the protocol-specific implementations implicitly depend on these checks. - errno = EINVAL; - return -1; - } - - if (!entry->vtable->getsockopt) { - errno = ENOPROTOOPT; - return -1; - } - - return entry->vtable->getsockopt(entry->data, level, optname, optval, optlen); + socklen_t *restrict optlen) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(sockfd); + if (!entry) + return -1; + + if (optval == NULL || optlen == NULL || *optlen < sizeof(int)) { + // FYI, the protocol-specific implementations implicitly depend on these + // checks. + errno = EINVAL; + return -1; + } + + if (!entry->vtable->getsockopt) { + errno = ENOPROTOOPT; + return -1; + } + + return entry->vtable->getsockopt(entry->data, level, optname, optval, optlen); } int setsockopt(int sockfd, int level, int optname, const void *optval, - socklen_t optlen) -{ - descriptor_table_entry_t *entry = descriptor_table_get_ref(sockfd); - if (!entry) - return -1; - - if (optval == NULL || optlen < sizeof(int)) { - // FYI, the protocol-specific implementations implicitly depend on these checks. - errno = EINVAL; - return -1; - } - - if (!entry->vtable->setsockopt) { - errno = ENOPROTOOPT; - return -1; - } - - return entry->vtable->setsockopt(entry->data, level, optname, optval, optlen); + socklen_t optlen) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(sockfd); + if (!entry) + return -1; + + if (optval == NULL || optlen < sizeof(int)) { + // FYI, the protocol-specific implementations implicitly depend on these + // checks. + errno = EINVAL; + return -1; + } + + if (!entry->vtable->setsockopt) { + errno = ENOPROTOOPT; + return -1; + } + + return entry->vtable->setsockopt(entry->data, level, optname, optval, optlen); } diff --git a/libc-bottom-half/sources/wasip2_file.c b/libc-bottom-half/sources/wasip2_file.c index ad580e91b..9affb49a2 100644 --- a/libc-bottom-half/sources/wasip2_file.c +++ b/libc-bottom-half/sources/wasip2_file.c @@ -62,10 +62,8 @@ static int file_get_read_stream(void *data, if (file->read_stream.__handle == 0) { filesystem_error_code_t error_code; bool ok = filesystem_method_descriptor_read_via_stream( - filesystem_borrow_descriptor(file->file_handle), - file->offset, - &file->read_stream, - &error_code); + filesystem_borrow_descriptor(file->file_handle), file->offset, + &file->read_stream, &error_code); if (!ok) { translate_error(error_code); return -1; @@ -90,15 +88,12 @@ static int file_get_write_stream(void *data, if (file->oflag & O_APPEND) { ok = filesystem_method_descriptor_append_via_stream( - filesystem_borrow_descriptor(file->file_handle), - &file->write_stream, + filesystem_borrow_descriptor(file->file_handle), &file->write_stream, &error_code); } else { ok = filesystem_method_descriptor_write_via_stream( - filesystem_borrow_descriptor(file->file_handle), - file->offset, - &file->write_stream, - &error_code); + filesystem_borrow_descriptor(file->file_handle), file->offset, + &file->write_stream, &error_code); } if (!ok) { translate_error(error_code); @@ -113,8 +108,7 @@ static int file_get_write_stream(void *data, return 0; } -static int file_get_file(void *data, - filesystem_borrow_descriptor_t *out_file) { +static int file_get_file(void *data, filesystem_borrow_descriptor_t *out_file) { file_t *file = (file_t *)data; *out_file = filesystem_borrow_descriptor(file->file_handle); return 0; @@ -125,18 +119,16 @@ static int file_fstat(void *data, struct stat *buf) { // Get the metadata hash for the file descriptor filesystem_metadata_hash_value_t metadata; filesystem_error_code_t error; - if (!filesystem_method_descriptor_metadata_hash(filesystem_borrow_descriptor(file->file_handle), - &metadata, - &error)) { + if (!filesystem_method_descriptor_metadata_hash( + filesystem_borrow_descriptor(file->file_handle), &metadata, &error)) { translate_error(error); return -1; } // Get the file metadata filesystem_descriptor_stat_t internal_stat; - bool stat_result = filesystem_method_descriptor_stat(filesystem_borrow_descriptor(file->file_handle), - &internal_stat, - &error); + bool stat_result = filesystem_method_descriptor_stat( + filesystem_borrow_descriptor(file->file_handle), &internal_stat, &error); if (!stat_result) { translate_error(error); return -1; @@ -150,14 +142,13 @@ static int file_fstat(void *data, struct stat *buf) { static int file_seek_end(file_t *file) { filesystem_descriptor_stat_t stat; filesystem_error_code_t error; - bool ok = filesystem_method_descriptor_stat(filesystem_borrow_descriptor(file->file_handle), - &stat, - &error); + bool ok = filesystem_method_descriptor_stat( + filesystem_borrow_descriptor(file->file_handle), &stat, &error); if (!ok) { translate_error(error); return -1; } - file->offset = (off_t) stat.size; + file->offset = (off_t)stat.size; return 0; } @@ -171,23 +162,23 @@ static off_t file_seek(void *data, off_t offset, int whence) { off_t result; switch (whence) { - case SEEK_SET: - result = offset; - break; - case SEEK_CUR: - result = file->offset + offset; - break; - case SEEK_END: { - // If we're in append mode we already reset to the end, but if we're not - // in append mode then do the reset to the end here. - if (!(file->oflag & O_APPEND) && file_seek_end(file) < 0) - return -1; - result = file->offset + offset; - break; - } - default: - errno = EINVAL; + case SEEK_SET: + result = offset; + break; + case SEEK_CUR: + result = file->offset + offset; + break; + case SEEK_END: { + // If we're in append mode we already reset to the end, but if we're not + // in append mode then do the reset to the end here. + if (!(file->oflag & O_APPEND) && file_seek_end(file) < 0) return -1; + result = file->offset + offset; + break; + } + default: + errno = EINVAL; + return -1; } if (result < 0) { errno = EINVAL; @@ -214,8 +205,10 @@ static int file_fcntl_getfl(void *data) { filesystem_descriptor_flags_t flags; filesystem_error_code_t error_code; - filesystem_borrow_descriptor_t file_handle = filesystem_borrow_descriptor(file->file_handle); - if (!filesystem_method_descriptor_get_flags(file_handle, &flags, &error_code)) { + filesystem_borrow_descriptor_t file_handle = + filesystem_borrow_descriptor(file->file_handle); + if (!filesystem_method_descriptor_get_flags(file_handle, &flags, + &error_code)) { translate_error(error_code); return -1; } @@ -227,9 +220,9 @@ static int file_fcntl_getfl(void *data) { else oflags |= O_RDONLY; } else if (flags & FILESYSTEM_DESCRIPTOR_FLAGS_WRITE) { - oflags |= O_WRONLY; + oflags |= O_WRONLY; } else { - oflags |= O_SEARCH; + oflags |= O_SEARCH; } return oflags; } @@ -242,16 +235,16 @@ static int file_fcntl_setfl(void *data, int flags) { } static descriptor_vtable_t file_vtable = { - .free = file_free, - .get_read_stream = file_get_read_stream, - .get_write_stream = file_get_write_stream, - .get_file = file_get_file, - .set_blocking = file_set_blocking, - .fstat = file_fstat, - .seek = file_seek, - .close_streams = file_close_streams, - .fcntl_getfl = file_fcntl_getfl, - .fcntl_setfl = file_fcntl_setfl, + .free = file_free, + .get_read_stream = file_get_read_stream, + .get_write_stream = file_get_write_stream, + .get_file = file_get_file, + .set_blocking = file_set_blocking, + .fstat = file_fstat, + .seek = file_seek, + .close_streams = file_close_streams, + .fcntl_getfl = file_fcntl_getfl, + .fcntl_setfl = file_fcntl_setfl, }; int __wasilibc_add_file(filesystem_own_descriptor_t file_handle, int oflag) { diff --git a/libc-bottom-half/sources/wasip2_file_utils.c b/libc-bottom-half/sources/wasip2_file_utils.c index 1ea313df4..90bbdd38b 100644 --- a/libc-bottom-half/sources/wasip2_file_utils.c +++ b/libc-bottom-half/sources/wasip2_file_utils.c @@ -1,8 +1,8 @@ #include -#include +#include #include #include -#include +#include #ifdef __wasilibc_use_wasip2 @@ -77,17 +77,15 @@ int wasip2_string_from_c(const char *s, wasip2_string_t *out) { errno = EILSEQ; return -1; } - out->ptr = (uint8_t*) s; + out->ptr = (uint8_t *)s; out->len = len; return 0; } // Gets an `output-stream` borrow from the `fd` provided. -int __wasilibc_write_stream(int fd, - streams_borrow_output_stream_t *out, - off_t **off, - poll_borrow_pollable_t *pollable) { - descriptor_table_entry_t* entry = descriptor_table_get_ref(fd); +int __wasilibc_write_stream(int fd, streams_borrow_output_stream_t *out, + off_t **off, poll_borrow_pollable_t *pollable) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(fd); if (!entry) return -1; if (!entry->vtable->get_write_stream) { @@ -108,11 +106,9 @@ int __wasilibc_write_stream(int fd, } // Gets an `input-stream` borrow from the `fd` provided. -int __wasilibc_read_stream(int fd, - streams_borrow_input_stream_t *out, - off_t **off, - poll_borrow_pollable_t *pollable) { - descriptor_table_entry_t* entry = descriptor_table_get_ref(fd); +int __wasilibc_read_stream(int fd, streams_borrow_input_stream_t *out, + off_t **off, poll_borrow_pollable_t *pollable) { + descriptor_table_entry_t *entry = descriptor_table_get_ref(fd); if (!entry) return -1; if (!entry->vtable->get_read_stream) { diff --git a/libc-bottom-half/sources/wasip2_stdio.c b/libc-bottom-half/sources/wasip2_stdio.c index e17ab1553..c933a2675 100644 --- a/libc-bottom-half/sources/wasip2_stdio.c +++ b/libc-bottom-half/sources/wasip2_stdio.c @@ -1,8 +1,8 @@ #ifdef __wasilibc_use_wasip2 -#include #include #include +#include #include #include #include @@ -95,29 +95,29 @@ static int stdio_fcntl_getfl(void *data) { static int stdio_isatty(void *data) { stdio_t *stdio = (stdio_t *)data; switch (stdio->fd) { - case 0: { - terminal_stdin_own_terminal_input_t term_input; - if (!terminal_stdin_get_terminal_stdin(&term_input)) - break; - terminal_input_terminal_input_drop_own(term_input); - return 1; - } - case 1: { - terminal_stdout_own_terminal_output_t term_output; - if (!terminal_stdout_get_terminal_stdout(&term_output)) - break; - terminal_output_terminal_output_drop_own(term_output); - return 1; - } - case 2: { - terminal_stderr_own_terminal_output_t term_output; - if (!terminal_stderr_get_terminal_stderr(&term_output)) - break; - terminal_output_terminal_output_drop_own(term_output); - return 1; - } - default: + case 0: { + terminal_stdin_own_terminal_input_t term_input; + if (!terminal_stdin_get_terminal_stdin(&term_input)) break; + terminal_input_terminal_input_drop_own(term_input); + return 1; + } + case 1: { + terminal_stdout_own_terminal_output_t term_output; + if (!terminal_stdout_get_terminal_stdout(&term_output)) + break; + terminal_output_terminal_output_drop_own(term_output); + return 1; + } + case 2: { + terminal_stderr_own_terminal_output_t term_output; + if (!terminal_stderr_get_terminal_stderr(&term_output)) + break; + terminal_output_terminal_output_drop_own(term_output); + return 1; + } + default: + break; } errno = ENOTTY; @@ -125,12 +125,12 @@ static int stdio_isatty(void *data) { } static descriptor_vtable_t stdio_vtable = { - .free = stdio_free, - .get_read_stream = stdio_get_read_stream, - .get_write_stream = stdio_get_write_stream, - .fstat = stdio_fstat, - .fcntl_getfl = stdio_fcntl_getfl, - .isatty = stdio_isatty, + .free = stdio_free, + .get_read_stream = stdio_get_read_stream, + .get_write_stream = stdio_get_write_stream, + .fstat = stdio_fstat, + .fcntl_getfl = stdio_fcntl_getfl, + .isatty = stdio_isatty, }; static int stdio_add(int fd) { diff --git a/libc-bottom-half/sources/wasip2_tcp.c b/libc-bottom-half/sources/wasip2_tcp.c index 666c9079c..537c6d4b3 100644 --- a/libc-bottom-half/sources/wasip2_tcp.c +++ b/libc-bottom-half/sources/wasip2_tcp.c @@ -38,7 +38,8 @@ typedef struct { network_error_code_t error_code; } tcp_socket_state_connect_failed_t; -// This is a tagged union. When adding/removing/renaming cases, be sure to keep the tag and union definitions in sync. +// This is a tagged union. When adding/removing/renaming cases, be sure to keep +// the tag and union definitions in sync. typedef struct { enum { TCP_SOCKET_STATE_UNBOUND, @@ -74,8 +75,7 @@ typedef struct { static descriptor_vtable_t tcp_vtable; static int tcp_add(tcp_own_tcp_socket_t socket, - network_ip_address_family_t family, - bool blocking, + network_ip_address_family_t family, bool blocking, tcp_socket_t **out) { tcp_socket_t *tcp = calloc(1, sizeof(tcp_socket_t)); if (!tcp) { @@ -106,16 +106,16 @@ static void tcp_free(void *data) { tcp_socket_t *tcp = (tcp_socket_t *)data; switch (tcp->state.tag) { - case TCP_SOCKET_STATE_CONNECTED: - if (tcp->state.connected.input_pollable.__handle != 0) - poll_pollable_drop_own(tcp->state.connected.input_pollable); - if (tcp->state.connected.output_pollable.__handle != 0) - poll_pollable_drop_own(tcp->state.connected.output_pollable); - streams_input_stream_drop_own(tcp->state.connected.input); - streams_output_stream_drop_own(tcp->state.connected.output); - break; - default: - break; + case TCP_SOCKET_STATE_CONNECTED: + if (tcp->state.connected.input_pollable.__handle != 0) + poll_pollable_drop_own(tcp->state.connected.input_pollable); + if (tcp->state.connected.output_pollable.__handle != 0) + poll_pollable_drop_own(tcp->state.connected.output_pollable); + streams_input_stream_drop_own(tcp->state.connected.input); + streams_output_stream_drop_own(tcp->state.connected.output); + break; + default: + break; } if (tcp->socket_pollable.__handle != 0) @@ -176,14 +176,14 @@ static int tcp_fstat(void *data, struct stat *buf) { static poll_borrow_pollable_t tcp_pollable(tcp_socket_t *socket) { if (socket->socket_pollable.__handle == 0) { - tcp_borrow_tcp_socket_t socket_borrow = tcp_borrow_tcp_socket(socket->socket); + tcp_borrow_tcp_socket_t socket_borrow = + tcp_borrow_tcp_socket(socket->socket); socket->socket_pollable = tcp_method_tcp_socket_subscribe(socket_borrow); } return poll_borrow_pollable(socket->socket_pollable); } -static int tcp_handle_error(tcp_socket_t *socket, - network_error_code_t error) { +static int tcp_handle_error(tcp_socket_t *socket, network_error_code_t error) { if (error == NETWORK_ERROR_CODE_WOULD_BLOCK && socket->blocking) { poll_method_pollable_block(tcp_pollable(socket)); } else { @@ -194,13 +194,12 @@ static int tcp_handle_error(tcp_socket_t *socket, return 0; } -static int tcp_accept4(void *data, - struct sockaddr *addr, - socklen_t *addrlen, +static int tcp_accept4(void *data, struct sockaddr *addr, socklen_t *addrlen, int flags) { tcp_socket_t *socket = (tcp_socket_t *)data; output_sockaddr_t output_addr; - if (!__wasi_sockets_utils__output_addr_validate(socket->family, addr, addrlen, &output_addr)) { + if (!__wasi_sockets_utils__output_addr_validate(socket->family, addr, addrlen, + &output_addr)) { errno = EINVAL; return -1; } @@ -229,7 +228,8 @@ static int tcp_accept4(void *data, if (output_addr.tag != OUTPUT_SOCKADDR_NULL) { network_ip_socket_address_t remote_address; - if (!tcp_method_tcp_socket_remote_address(client_borrow, &remote_address, &error)) { + if (!tcp_method_tcp_socket_remote_address(client_borrow, &remote_address, + &error)) { // TODO wasi-sockets: How to recover from this in a POSIX compatible way? abort(); } @@ -238,7 +238,8 @@ static int tcp_accept4(void *data, } tcp_socket_t *client_socket; - int client_fd = tcp_add(client, socket->family, (flags & SOCK_NONBLOCK) == 0, &client_socket); + int client_fd = tcp_add(client, socket->family, (flags & SOCK_NONBLOCK) == 0, + &client_socket); if (client_fd < 0) { streams_input_stream_drop_own(input); streams_output_stream_drop_own(output); @@ -246,24 +247,28 @@ static int tcp_accept4(void *data, } client_socket->state.tag = TCP_SOCKET_STATE_CONNECTED; - memset(&client_socket->state.connected, 0, sizeof(client_socket->state.connected)); + memset(&client_socket->state.connected, 0, + sizeof(client_socket->state.connected)); client_socket->state.connected.input = input; client_socket->state.connected.output = output; client_socket->fake_nodelay = socket->fake_nodelay; return client_fd; } -static int tcp_do_bind(tcp_socket_t *socket, network_ip_socket_address_t *address) { +static int tcp_do_bind(tcp_socket_t *socket, + network_ip_socket_address_t *address) { if (socket->state.tag != TCP_SOCKET_STATE_UNBOUND) { errno = EINVAL; return -1; } network_error_code_t error; - network_borrow_network_t network_borrow = __wasi_sockets_utils__borrow_network(); + network_borrow_network_t network_borrow = + __wasi_sockets_utils__borrow_network(); tcp_borrow_tcp_socket_t socket_borrow = tcp_borrow_tcp_socket(socket->socket); - if (!tcp_method_tcp_socket_start_bind(socket_borrow, network_borrow, address, &error)) { + if (!tcp_method_tcp_socket_start_bind(socket_borrow, network_borrow, address, + &error)) { errno = __wasi_sockets_utils__map_error(error); return -1; } @@ -279,51 +284,60 @@ static int tcp_do_bind(tcp_socket_t *socket, network_ip_socket_address_t *addres return 0; } -static int tcp_bind(void *data, const struct sockaddr *addr, socklen_t addrlen) { +static int tcp_bind(void *data, const struct sockaddr *addr, + socklen_t addrlen) { tcp_socket_t *socket = (tcp_socket_t *)data; network_ip_socket_address_t local_address; int parse_err; - if (!__wasi_sockets_utils__parse_address(socket->family, addr, addrlen, &local_address, &parse_err)) { + if (!__wasi_sockets_utils__parse_address(socket->family, addr, addrlen, + &local_address, &parse_err)) { errno = parse_err; return -1; } return tcp_do_bind(socket, &local_address); } -static int tcp_connect(void *data, const struct sockaddr *addr, socklen_t addrlen) { +static int tcp_connect(void *data, const struct sockaddr *addr, + socklen_t addrlen) { tcp_socket_t *socket = (tcp_socket_t *)data; network_ip_socket_address_t remote_address; int parse_err; if (!__wasi_sockets_utils__parse_address(socket->family, addr, addrlen, - &remote_address, &parse_err)) { + &remote_address, &parse_err)) { errno = parse_err; return -1; } switch (socket->state.tag) { - case TCP_SOCKET_STATE_UNBOUND: - case TCP_SOCKET_STATE_BOUND: - // These can initiate a connect. - break; - case TCP_SOCKET_STATE_CONNECTING: - errno = EALREADY; - return -1; - case TCP_SOCKET_STATE_CONNECTED: - errno = EISCONN; - return -1; - case TCP_SOCKET_STATE_CONNECT_FAILED: // POSIX: "If connect() fails, the state of the socket is unspecified. Conforming applications should close the file descriptor and create a new socket before attempting to reconnect." - case TCP_SOCKET_STATE_LISTENING: - default: - errno = EOPNOTSUPP; - return -1; + case TCP_SOCKET_STATE_UNBOUND: + case TCP_SOCKET_STATE_BOUND: + // These can initiate a connect. + break; + case TCP_SOCKET_STATE_CONNECTING: + errno = EALREADY; + return -1; + case TCP_SOCKET_STATE_CONNECTED: + errno = EISCONN; + return -1; + case TCP_SOCKET_STATE_CONNECT_FAILED: // POSIX: "If connect() fails, the state + // of the socket is unspecified. + // Conforming applications should close + // the file descriptor and create a new + // socket before attempting to + // reconnect." + case TCP_SOCKET_STATE_LISTENING: + default: + errno = EOPNOTSUPP; + return -1; } network_error_code_t error; - network_borrow_network_t network_borrow = __wasi_sockets_utils__borrow_network(); + network_borrow_network_t network_borrow = + __wasi_sockets_utils__borrow_network(); tcp_borrow_tcp_socket_t socket_borrow = tcp_borrow_tcp_socket(socket->socket); if (!tcp_method_tcp_socket_start_connect(socket_borrow, network_borrow, - &remote_address, &error)) { + &remote_address, &error)) { errno = __wasi_sockets_utils__map_error(error); return -1; } @@ -336,7 +350,7 @@ static int tcp_connect(void *data, const struct sockaddr *addr, socklen_t addrle while (!tcp_method_tcp_socket_finish_connect(socket_borrow, &io, &error)) { if (tcp_handle_error(socket, error) < 0) { if (error == NETWORK_ERROR_CODE_WOULD_BLOCK) { - errno = EINPROGRESS; + errno = EINPROGRESS; } else { socket->state.tag = TCP_SOCKET_STATE_CONNECT_FAILED; socket->state.connect_failed.error_code = error; @@ -357,10 +371,12 @@ static int tcp_connect(void *data, const struct sockaddr *addr, socklen_t addrle return 0; } -static int tcp_getsockname(void *data, struct sockaddr *addr, socklen_t *addrlen) { +static int tcp_getsockname(void *data, struct sockaddr *addr, + socklen_t *addrlen) { tcp_socket_t *socket = (tcp_socket_t *)data; output_sockaddr_t output_addr; - if (!__wasi_sockets_utils__output_addr_validate(socket->family, addr, addrlen, &output_addr)) { + if (!__wasi_sockets_utils__output_addr_validate(socket->family, addr, addrlen, + &output_addr)) { errno = EINVAL; return -1; } @@ -371,20 +387,20 @@ static int tcp_getsockname(void *data, struct sockaddr *addr, socklen_t *addrlen } switch (socket->state.tag) { - case TCP_SOCKET_STATE_UNBOUND: - errno = EINVAL; - return -1; + case TCP_SOCKET_STATE_UNBOUND: + errno = EINVAL; + return -1; - case TCP_SOCKET_STATE_BOUND: - case TCP_SOCKET_STATE_CONNECTING: - case TCP_SOCKET_STATE_CONNECT_FAILED: - case TCP_SOCKET_STATE_LISTENING: - case TCP_SOCKET_STATE_CONNECTED: - // OK. Continue.. - break; + case TCP_SOCKET_STATE_BOUND: + case TCP_SOCKET_STATE_CONNECTING: + case TCP_SOCKET_STATE_CONNECT_FAILED: + case TCP_SOCKET_STATE_LISTENING: + case TCP_SOCKET_STATE_CONNECTED: + // OK. Continue.. + break; - default: /* unreachable */ - abort(); + default: /* unreachable */ + abort(); } network_error_code_t error; @@ -402,8 +418,8 @@ static int tcp_getsockname(void *data, struct sockaddr *addr, socklen_t *addrlen int tcp_getpeername(void *data, struct sockaddr *addr, socklen_t *addrlen) { tcp_socket_t *socket = (tcp_socket_t *)data; output_sockaddr_t output_addr; - if (!__wasi_sockets_utils__output_addr_validate( - socket->family, addr, addrlen, &output_addr)) { + if (!__wasi_sockets_utils__output_addr_validate(socket->family, addr, addrlen, + &output_addr)) { errno = EINVAL; return -1; } @@ -414,20 +430,20 @@ int tcp_getpeername(void *data, struct sockaddr *addr, socklen_t *addrlen) { } switch (socket->state.tag) { - case TCP_SOCKET_STATE_UNBOUND: - case TCP_SOCKET_STATE_BOUND: - case TCP_SOCKET_STATE_CONNECTING: - case TCP_SOCKET_STATE_CONNECT_FAILED: - case TCP_SOCKET_STATE_LISTENING: - errno = ENOTCONN; - return -1; + case TCP_SOCKET_STATE_UNBOUND: + case TCP_SOCKET_STATE_BOUND: + case TCP_SOCKET_STATE_CONNECTING: + case TCP_SOCKET_STATE_CONNECT_FAILED: + case TCP_SOCKET_STATE_LISTENING: + errno = ENOTCONN; + return -1; - case TCP_SOCKET_STATE_CONNECTED: - // OK. Continue.. - break; + case TCP_SOCKET_STATE_CONNECTED: + // OK. Continue.. + break; - default: /* unreachable */ - abort(); + default: /* unreachable */ + abort(); } network_error_code_t error; @@ -445,38 +461,39 @@ int tcp_getpeername(void *data, struct sockaddr *addr, socklen_t *addrlen) { static int tcp_listen(void *data, int backlog) { tcp_socket_t *socket = (tcp_socket_t *)data; network_error_code_t error; - tcp_borrow_tcp_socket_t socket_borrow = - tcp_borrow_tcp_socket(socket->socket); + tcp_borrow_tcp_socket_t socket_borrow = tcp_borrow_tcp_socket(socket->socket); switch (socket->state.tag) { - case TCP_SOCKET_STATE_UNBOUND: { - // Socket is not explicitly bound by the user. We'll do it for them: + case TCP_SOCKET_STATE_UNBOUND: { + // Socket is not explicitly bound by the user. We'll do it for them: - network_ip_socket_address_t any = __wasi_sockets_utils__any_addr(socket->family); - if (tcp_do_bind(socket, &any) < 0) - return -1; + network_ip_socket_address_t any = + __wasi_sockets_utils__any_addr(socket->family); + if (tcp_do_bind(socket, &any) < 0) + return -1; - if (socket->state.tag != TCP_SOCKET_STATE_BOUND) { - abort(); - } - // Great! We'll continue below. - break; + if (socket->state.tag != TCP_SOCKET_STATE_BOUND) { + abort(); } - case TCP_SOCKET_STATE_BOUND: - // Great! We'll continue below. - break; - case TCP_SOCKET_STATE_LISTENING: - // We can only update the backlog size. - break; - case TCP_SOCKET_STATE_CONNECTING: - case TCP_SOCKET_STATE_CONNECTED: - case TCP_SOCKET_STATE_CONNECT_FAILED: - default: - errno = EINVAL; - return -1; + // Great! We'll continue below. + break; + } + case TCP_SOCKET_STATE_BOUND: + // Great! We'll continue below. + break; + case TCP_SOCKET_STATE_LISTENING: + // We can only update the backlog size. + break; + case TCP_SOCKET_STATE_CONNECTING: + case TCP_SOCKET_STATE_CONNECTED: + case TCP_SOCKET_STATE_CONNECT_FAILED: + default: + errno = EINVAL; + return -1; } - if (!tcp_method_tcp_socket_set_listen_backlog_size(socket_borrow, backlog, &error)) { + if (!tcp_method_tcp_socket_set_listen_backlog_size(socket_borrow, backlog, + &error)) { errno = __wasi_sockets_utils__map_error(error); return -1; } @@ -486,7 +503,8 @@ static int tcp_listen(void *data, int backlog) { return 0; } - network_borrow_network_t network_borrow = __wasi_sockets_utils__borrow_network(); + network_borrow_network_t network_borrow = + __wasi_sockets_utils__borrow_network(); if (!tcp_method_tcp_socket_start_listen(socket_borrow, &error)) { errno = __wasi_sockets_utils__map_error(error); return -1; @@ -503,14 +521,15 @@ static int tcp_listen(void *data, int backlog) { return 0; } -static ssize_t tcp_recvfrom(void *data, void *buffer, - size_t length, int flags, struct sockaddr *addr, - socklen_t *addrlen) { +static ssize_t tcp_recvfrom(void *data, void *buffer, size_t length, int flags, + struct sockaddr *addr, socklen_t *addrlen) { tcp_socket_t *socket = (tcp_socket_t *)data; // TODO wasi-sockets: flags: // - MSG_WAITALL: we can probably support these relatively easy. - // - MSG_OOB: could be shimmed by always responding that no OOB data is available. - // - MSG_PEEK: could be shimmed by performing the receive into a local socket-specific buffer. And on subsequent receives first check that buffer. + // - MSG_OOB: could be shimmed by always responding that no OOB data is + // available. + // - MSG_PEEK: could be shimmed by performing the receive into a local + // socket-specific buffer. And on subsequent receives first check that buffer. const int supported_flags = MSG_DONTWAIT; if ((flags & supported_flags) != flags) { @@ -534,12 +553,14 @@ static ssize_t tcp_recvfrom(void *data, void *buffer, should_block = false; } - streams_borrow_input_stream_t rx_borrow = streams_borrow_input_stream(connection->input); + streams_borrow_input_stream_t rx_borrow = + streams_borrow_input_stream(connection->input); while (true) { wasip2_list_u8_t result; streams_stream_error_t error; if (!streams_method_input_stream_read(rx_borrow, length, &result, &error)) - // TODO wasi-sockets: wasi-sockets has no way to recover TCP stream errors yet. + // TODO wasi-sockets: wasi-sockets has no way to recover TCP stream errors + // yet. return wasip2_handle_read_error(error); if (result.len) { @@ -553,12 +574,14 @@ static ssize_t tcp_recvfrom(void *data, void *buffer, } if (connection->input_pollable.__handle == 0) - connection->input_pollable = streams_method_input_stream_subscribe(rx_borrow); - poll_borrow_pollable_t pollable_borrow = poll_borrow_pollable(connection->input_pollable); + connection->input_pollable = + streams_method_input_stream_subscribe(rx_borrow); + poll_borrow_pollable_t pollable_borrow = + poll_borrow_pollable(connection->input_pollable); if (socket->recv_timeout != 0) { poll_own_pollable_t timeout_pollable = - monotonic_clock_subscribe_duration(socket->recv_timeout); + monotonic_clock_subscribe_duration(socket->recv_timeout); poll_list_borrow_pollable_t pollables; poll_borrow_pollable_t pollables_ptr[2]; pollables.ptr = pollables_ptr; @@ -583,8 +606,8 @@ static ssize_t tcp_recvfrom(void *data, void *buffer, } } -static ssize_t tcp_sendto(void *data, const void *buffer, - size_t length, int flags, const struct sockaddr *addr, +static ssize_t tcp_sendto(void *data, const void *buffer, size_t length, + int flags, const struct sockaddr *addr, socklen_t addrlen) { tcp_socket_t *socket = (tcp_socket_t *)data; const int supported_flags = MSG_DONTWAIT | MSG_NOSIGNAL; @@ -617,19 +640,22 @@ static ssize_t tcp_sendto(void *data, const void *buffer, // requested or not. } - streams_borrow_output_stream_t tx_borrow = streams_borrow_output_stream(connection->output); + streams_borrow_output_stream_t tx_borrow = + streams_borrow_output_stream(connection->output); while (true) { streams_stream_error_t error; uint64_t count; if (!streams_method_output_stream_check_write(tx_borrow, &count, &error)) - // TODO wasi-sockets: wasi-sockets has no way to recover stream errors yet. + // TODO wasi-sockets: wasi-sockets has no way to recover stream errors + // yet. return wasip2_handle_write_error(error); if (count) { count = count < length ? count : length; - wasip2_list_u8_t list = { .ptr = (uint8_t *)buffer, .len = count }; + wasip2_list_u8_t list = {.ptr = (uint8_t *)buffer, .len = count}; if (!streams_method_output_stream_write(tx_borrow, &list, &error)) { - // TODO wasi-sockets: wasi-sockets has no way to recover TCP stream errors yet. + // TODO wasi-sockets: wasi-sockets has no way to recover TCP stream + // errors yet. return wasip2_handle_write_error(error); } else { return count; @@ -641,12 +667,14 @@ static ssize_t tcp_sendto(void *data, const void *buffer, } if (connection->output_pollable.__handle == 0) - connection->output_pollable = streams_method_output_stream_subscribe(tx_borrow); - poll_borrow_pollable_t pollable_borrow = poll_borrow_pollable(connection->output_pollable); + connection->output_pollable = + streams_method_output_stream_subscribe(tx_borrow); + poll_borrow_pollable_t pollable_borrow = + poll_borrow_pollable(connection->output_pollable); if (socket->send_timeout != 0) { monotonic_clock_own_pollable_t timeout_pollable = - monotonic_clock_subscribe_duration(socket->send_timeout); + monotonic_clock_subscribe_duration(socket->send_timeout); poll_list_borrow_pollable_t pollables; poll_borrow_pollable_t pollables_ptr[2]; pollables.ptr = pollables_ptr; @@ -675,18 +703,18 @@ static int tcp_shutdown(void *data, int posix_how) { tcp_socket_t *socket = (tcp_socket_t *)data; tcp_shutdown_type_t wasi_how; switch (posix_how) { - case SHUT_RD: - wasi_how = TCP_SHUTDOWN_TYPE_RECEIVE; - break; - case SHUT_WR: - wasi_how = TCP_SHUTDOWN_TYPE_SEND; - break; - case SHUT_RDWR: - wasi_how = TCP_SHUTDOWN_TYPE_BOTH; - break; - default: - errno = EINVAL; - return -1; + case SHUT_RD: + wasi_how = TCP_SHUTDOWN_TYPE_RECEIVE; + break; + case SHUT_WR: + wasi_how = TCP_SHUTDOWN_TYPE_SEND; + break; + case SHUT_RDWR: + wasi_how = TCP_SHUTDOWN_TYPE_BOTH; + break; + default: + errno = EINVAL; + return -1; } tcp_socket_state_connected_t *connection; @@ -718,7 +746,7 @@ static int tcp_shutdown(void *data, int posix_how) { } static int tcp_getsockopt(void *data, int level, int optname, - void *restrict optval, socklen_t *restrict optlen) { + void *restrict optval, socklen_t *restrict optlen) { tcp_socket_t *socket = (tcp_socket_t *)data; int value = 0; @@ -726,211 +754,223 @@ static int tcp_getsockopt(void *data, int level, int optname, tcp_borrow_tcp_socket_t socket_borrow = tcp_borrow_tcp_socket(socket->socket); switch (level) { - case SOL_SOCKET: - switch (optname) { - case SO_TYPE: - value = SOCK_STREAM; - break; - case SO_PROTOCOL: - value = IPPROTO_TCP; - break; - - case SO_DOMAIN: - value = __wasi_sockets_utils__posix_family(socket->family); - break; - - case SO_ERROR: - if (socket->state.tag == TCP_SOCKET_STATE_CONNECT_FAILED) { - value = __wasi_sockets_utils__map_error(socket->state.connect_failed.error_code); - socket->state.connect_failed.error_code = 0; - } else if (socket->state.tag == TCP_SOCKET_STATE_CONNECTING) { - value = EINPROGRESS; - } else { - value = 0; - } - break; - - case SO_ACCEPTCONN: { - bool is_listening = socket->state.tag == TCP_SOCKET_STATE_LISTENING; - // Sanity check. - if (is_listening != tcp_method_tcp_socket_is_listening(socket_borrow)) { - abort(); - } - value = is_listening; - break; - } - case SO_KEEPALIVE: { - bool result; - if (!tcp_method_tcp_socket_keep_alive_enabled(socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - value = result; - break; - } - case SO_RCVBUF: { - uint64_t result; - if (!tcp_method_tcp_socket_receive_buffer_size(socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - if (result > INT_MAX) { - abort(); - } - - value = result; - break; - } - case SO_SNDBUF: { - uint64_t result; - if (!tcp_method_tcp_socket_send_buffer_size(socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - if (result > INT_MAX) { - abort(); - } - - value = result; - break; - } - case SO_REUSEADDR: - value = socket->fake_reuseaddr; - break; - case SO_RCVTIMEO: { - struct timeval tv = duration_to_timeval(socket->recv_timeout); - memcpy(optval, &tv, *optlen < sizeof(struct timeval) ? *optlen : sizeof(struct timeval)); - *optlen = sizeof(struct timeval); - return 0; - } - case SO_SNDTIMEO: { - struct timeval tv = duration_to_timeval(socket->send_timeout); - memcpy(optval, &tv, *optlen < sizeof(struct timeval) ? *optlen : sizeof(struct timeval)); - *optlen = sizeof(struct timeval); - return 0; - } - default: - errno = ENOPROTOOPT; - return -1; + case SOL_SOCKET: + switch (optname) { + case SO_TYPE: + value = SOCK_STREAM; + break; + case SO_PROTOCOL: + value = IPPROTO_TCP; + break; + + case SO_DOMAIN: + value = __wasi_sockets_utils__posix_family(socket->family); + break; + + case SO_ERROR: + if (socket->state.tag == TCP_SOCKET_STATE_CONNECT_FAILED) { + value = __wasi_sockets_utils__map_error( + socket->state.connect_failed.error_code); + socket->state.connect_failed.error_code = 0; + } else if (socket->state.tag == TCP_SOCKET_STATE_CONNECTING) { + value = EINPROGRESS; + } else { + value = 0; } break; - case SOL_IP: - switch (optname) { - case IP_TTL: { - if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV4) { - errno = EAFNOSUPPORT; - return -1; - } - - uint8_t result; - if (!tcp_method_tcp_socket_hop_limit(socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - value = result; - break; - } - default: - errno = ENOPROTOOPT; - return -1; + case SO_ACCEPTCONN: { + bool is_listening = socket->state.tag == TCP_SOCKET_STATE_LISTENING; + // Sanity check. + if (is_listening != tcp_method_tcp_socket_is_listening(socket_borrow)) { + abort(); } + value = is_listening; break; + } + case SO_KEEPALIVE: { + bool result; + if (!tcp_method_tcp_socket_keep_alive_enabled(socket_borrow, &result, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + value = result; + break; + } + case SO_RCVBUF: { + uint64_t result; + if (!tcp_method_tcp_socket_receive_buffer_size(socket_borrow, &result, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } - case SOL_IPV6: - switch (optname) { - case IPV6_UNICAST_HOPS: { - if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV6) { - errno = EAFNOSUPPORT; - return -1; - } - - uint8_t result; - if (!tcp_method_tcp_socket_hop_limit(socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - value = result; - break; - } - default: - errno = ENOPROTOOPT; - return -1; + if (result > INT_MAX) { + abort(); } + + value = result; break; + } + case SO_SNDBUF: { + uint64_t result; + if (!tcp_method_tcp_socket_send_buffer_size(socket_borrow, &result, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } - case SOL_TCP: - switch (optname) { - case TCP_NODELAY: { - value = socket->fake_nodelay; - break; - } - case TCP_KEEPIDLE: { - tcp_duration_t result_ns; - if (!tcp_method_tcp_socket_keep_alive_idle_time( - socket_borrow, &result_ns, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - uint64_t result_s = result_ns / NS_PER_S; - if (result_s == 0) { - result_s = 1; // Value was rounded down to zero. Round it up instead, because 0 is an invalid value for this socket option. - } - - if (result_s > INT_MAX) { - abort(); - } - - value = result_s; - break; - } - case TCP_KEEPINTVL: { - tcp_duration_t result_ns; - if (!tcp_method_tcp_socket_keep_alive_interval(socket_borrow, &result_ns, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - uint64_t result_s = result_ns / NS_PER_S; - if (result_s == 0) { - result_s = 1; // Value was rounded down to zero. Round it up instead, because 0 is an invalid value for this socket option. - } - - if (result_s > INT_MAX) { - abort(); - } - - value = result_s; - break; - } - case TCP_KEEPCNT: { - uint32_t result; - if (!tcp_method_tcp_socket_keep_alive_count(socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - if (result > INT_MAX) { - abort(); - } - - value = result; - break; - } - default: - errno = ENOPROTOOPT; - return -1; + if (result > INT_MAX) { + abort(); + } + + value = result; + break; + } + case SO_REUSEADDR: + value = socket->fake_reuseaddr; + break; + case SO_RCVTIMEO: { + struct timeval tv = duration_to_timeval(socket->recv_timeout); + memcpy(optval, &tv, + *optlen < sizeof(struct timeval) ? *optlen + : sizeof(struct timeval)); + *optlen = sizeof(struct timeval); + return 0; + } + case SO_SNDTIMEO: { + struct timeval tv = duration_to_timeval(socket->send_timeout); + memcpy(optval, &tv, + *optlen < sizeof(struct timeval) ? *optlen + : sizeof(struct timeval)); + *optlen = sizeof(struct timeval); + return 0; + } + default: + errno = ENOPROTOOPT; + return -1; + } + break; + + case SOL_IP: + switch (optname) { + case IP_TTL: { + if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV4) { + errno = EAFNOSUPPORT; + return -1; + } + + uint8_t result; + if (!tcp_method_tcp_socket_hop_limit(socket_borrow, &result, &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + value = result; + break; + } + default: + errno = ENOPROTOOPT; + return -1; + } + break; + + case SOL_IPV6: + switch (optname) { + case IPV6_UNICAST_HOPS: { + if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV6) { + errno = EAFNOSUPPORT; + return -1; + } + + uint8_t result; + if (!tcp_method_tcp_socket_hop_limit(socket_borrow, &result, &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + value = result; + break; + } + default: + errno = ENOPROTOOPT; + return -1; + } + break; + + case SOL_TCP: + switch (optname) { + case TCP_NODELAY: { + value = socket->fake_nodelay; + break; + } + case TCP_KEEPIDLE: { + tcp_duration_t result_ns; + if (!tcp_method_tcp_socket_keep_alive_idle_time(socket_borrow, &result_ns, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + uint64_t result_s = result_ns / NS_PER_S; + if (result_s == 0) { + result_s = 1; // Value was rounded down to zero. Round it up instead, + // because 0 is an invalid value for this socket option. + } + + if (result_s > INT_MAX) { + abort(); + } + + value = result_s; + break; + } + case TCP_KEEPINTVL: { + tcp_duration_t result_ns; + if (!tcp_method_tcp_socket_keep_alive_interval(socket_borrow, &result_ns, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + uint64_t result_s = result_ns / NS_PER_S; + if (result_s == 0) { + result_s = 1; // Value was rounded down to zero. Round it up instead, + // because 0 is an invalid value for this socket option. + } + + if (result_s > INT_MAX) { + abort(); } + + value = result_s; break; + } + case TCP_KEEPCNT: { + uint32_t result; + if (!tcp_method_tcp_socket_keep_alive_count(socket_borrow, &result, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + if (result > INT_MAX) { + abort(); + } + + value = result; + break; + } default: errno = ENOPROTOOPT; return -1; + } + break; + + default: + errno = ENOPROTOOPT; + return -1; } // Copy out integer value. @@ -939,8 +979,8 @@ static int tcp_getsockopt(void *data, int level, int optname, return 0; } -int tcp_setsockopt(void *data, int level, int optname, - const void *optval, socklen_t optlen) { +int tcp_setsockopt(void *data, int level, int optname, const void *optval, + socklen_t optlen) { tcp_socket_t *socket = (tcp_socket_t *)data; int intval = *(int *)optval; @@ -948,211 +988,208 @@ int tcp_setsockopt(void *data, int level, int optname, tcp_borrow_tcp_socket_t socket_borrow = tcp_borrow_tcp_socket(socket->socket); switch (level) { - case SOL_SOCKET: - switch (optname) { - case SO_KEEPALIVE: { - if (!tcp_method_tcp_socket_set_keep_alive_enabled( - socket_borrow, intval != 0, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - case SO_RCVBUF: { - if (!tcp_method_tcp_socket_set_receive_buffer_size( - socket_borrow, intval, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - case SO_SNDBUF: { - if (!tcp_method_tcp_socket_set_send_buffer_size( - socket_borrow, intval, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - case SO_REUSEADDR: { - // As of this writing, WASI has no support for changing SO_REUSEADDR - // -- it's enabled by default and cannot be disabled. To keep - // applications happy, we pretend to support enabling and disabling - // it. - socket->fake_reuseaddr = (intval != 0); - return 0; - } - case SO_RCVTIMEO: { - struct timeval* tv = (struct timeval*) optval; - if (!timeval_to_duration(tv, &socket->recv_timeout)) { - errno = EINVAL; - return -1; - } - return 0; - } - case SO_SNDTIMEO: { - struct timeval* tv = (struct timeval*) optval; - if (!timeval_to_duration(tv, &socket->send_timeout)) { - errno = EINVAL; - return -1; - } - return 0; - } - default: - errno = ENOPROTOOPT; - return -1; + case SOL_SOCKET: + switch (optname) { + case SO_KEEPALIVE: { + if (!tcp_method_tcp_socket_set_keep_alive_enabled(socket_borrow, + intval != 0, &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; } - break; - case SOL_IP: - switch (optname) { - case IP_TTL: { - if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV4) { - errno = EAFNOSUPPORT; - return -1; - } - - if (intval < 0 || intval > UINT8_MAX) { - errno = EINVAL; - return -1; - } - - if (!tcp_method_tcp_socket_set_hop_limit(socket_borrow, intval, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - default: - errno = ENOPROTOOPT; - return -1; + return 0; + } + case SO_RCVBUF: { + if (!tcp_method_tcp_socket_set_receive_buffer_size(socket_borrow, intval, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; } - break; - case SOL_IPV6: - switch (optname) { - case IPV6_UNICAST_HOPS: { - if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV6) { - errno = EAFNOSUPPORT; - return -1; - } - - if (intval < 0 || intval > UINT8_MAX) { - errno = EINVAL; - return -1; - } - - if (!tcp_method_tcp_socket_set_hop_limit(socket_borrow, intval, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - default: - errno = ENOPROTOOPT; - return -1; + return 0; + } + case SO_SNDBUF: { + if (!tcp_method_tcp_socket_set_send_buffer_size(socket_borrow, intval, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; } - break; - case SOL_TCP: - switch (optname) { - case TCP_NODELAY: { - // At the time of writing, WASI has no support for TCP_NODELAY. - // Yet, many applications expect this option to be implemented. - // To ensure those applications can run on WASI at all, we fake - // support for it by recording the value, but not doing anything - // with it. - // If/when WASI adds true support, we can remove this workaround - // and implement it properly. From the application's perspective - // the "worst" thing that can then happen is that it automagically - // becomes faster. - socket->fake_nodelay = (intval != 0); - return 0; - } - case TCP_KEEPIDLE: { - tcp_duration_t duration = intval * NS_PER_S; - if (!tcp_method_tcp_socket_set_keep_alive_idle_time( - socket_borrow, duration, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - case TCP_KEEPINTVL: { - tcp_duration_t duration = intval * NS_PER_S; - if (!tcp_method_tcp_socket_set_keep_alive_interval( - socket_borrow, duration, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - case TCP_KEEPCNT: { - if (!tcp_method_tcp_socket_set_keep_alive_count( - socket_borrow, intval, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - default: - errno = ENOPROTOOPT; - return -1; + return 0; + } + case SO_REUSEADDR: { + // As of this writing, WASI has no support for changing SO_REUSEADDR + // -- it's enabled by default and cannot be disabled. To keep + // applications happy, we pretend to support enabling and disabling + // it. + socket->fake_reuseaddr = (intval != 0); + return 0; + } + case SO_RCVTIMEO: { + struct timeval *tv = (struct timeval *)optval; + if (!timeval_to_duration(tv, &socket->recv_timeout)) { + errno = EINVAL; + return -1; + } + return 0; + } + case SO_SNDTIMEO: { + struct timeval *tv = (struct timeval *)optval; + if (!timeval_to_duration(tv, &socket->send_timeout)) { + errno = EINVAL; + return -1; + } + return 0; + } + default: + errno = ENOPROTOOPT; + return -1; + } + break; + + case SOL_IP: + switch (optname) { + case IP_TTL: { + if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV4) { + errno = EAFNOSUPPORT; + return -1; } - break; + if (intval < 0 || intval > UINT8_MAX) { + errno = EINVAL; + return -1; + } + + if (!tcp_method_tcp_socket_set_hop_limit(socket_borrow, intval, &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + return 0; + } + default: + errno = ENOPROTOOPT; + return -1; + } + break; + + case SOL_IPV6: + switch (optname) { + case IPV6_UNICAST_HOPS: { + if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV6) { + errno = EAFNOSUPPORT; + return -1; + } + + if (intval < 0 || intval > UINT8_MAX) { + errno = EINVAL; + return -1; + } + + if (!tcp_method_tcp_socket_set_hop_limit(socket_borrow, intval, &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + return 0; + } + default: + errno = ENOPROTOOPT; + return -1; + } + break; + + case SOL_TCP: + switch (optname) { + case TCP_NODELAY: { + // At the time of writing, WASI has no support for TCP_NODELAY. + // Yet, many applications expect this option to be implemented. + // To ensure those applications can run on WASI at all, we fake + // support for it by recording the value, but not doing anything + // with it. + // If/when WASI adds true support, we can remove this workaround + // and implement it properly. From the application's perspective + // the "worst" thing that can then happen is that it automagically + // becomes faster. + socket->fake_nodelay = (intval != 0); + return 0; + } + case TCP_KEEPIDLE: { + tcp_duration_t duration = intval * NS_PER_S; + if (!tcp_method_tcp_socket_set_keep_alive_idle_time(socket_borrow, + duration, &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + return 0; + } + case TCP_KEEPINTVL: { + tcp_duration_t duration = intval * NS_PER_S; + if (!tcp_method_tcp_socket_set_keep_alive_interval(socket_borrow, + duration, &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + return 0; + } + case TCP_KEEPCNT: { + if (!tcp_method_tcp_socket_set_keep_alive_count(socket_borrow, intval, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + return 0; + } default: errno = ENOPROTOOPT; return -1; + } + break; + + default: + errno = ENOPROTOOPT; + return -1; } } -static int tcp_poll_register(void *data, - poll_state_t *state, - short events) { +static int tcp_poll_register(void *data, poll_state_t *state, short events) { tcp_socket_t *socket = (tcp_socket_t *)data; switch (socket->state.tag) { - case TCP_SOCKET_STATE_CONNECTING: - case TCP_SOCKET_STATE_LISTENING: { - if ((events & (POLLRDNORM | POLLWRNORM)) != 0) - return __wasilibc_poll_add(state, events, tcp_pollable(socket)); - break; - } + case TCP_SOCKET_STATE_CONNECTING: + case TCP_SOCKET_STATE_LISTENING: { + if ((events & (POLLRDNORM | POLLWRNORM)) != 0) + return __wasilibc_poll_add(state, events, tcp_pollable(socket)); + break; + } - case TCP_SOCKET_STATE_CONNECTED: { - if ((events & POLLRDNORM) != 0) { - if (__wasilibc_poll_add_input_stream( - state, - streams_borrow_input_stream(socket->state.connected.input), + case TCP_SOCKET_STATE_CONNECTED: { + if ((events & POLLRDNORM) != 0) { + if (__wasilibc_poll_add_input_stream( + state, streams_borrow_input_stream(socket->state.connected.input), &socket->state.connected.input_pollable) < 0) - return -1; - } - if ((events & POLLWRNORM) != 0) { - if (__wasilibc_poll_add_output_stream( + return -1; + } + if ((events & POLLWRNORM) != 0) { + if (__wasilibc_poll_add_output_stream( state, streams_borrow_output_stream(socket->state.connected.output), &socket->state.connected.output_pollable) < 0) - return -1; - } - break; + return -1; } + break; + } - case TCP_SOCKET_STATE_CONNECT_FAILED: { - __wasilibc_poll_ready(state, events); - break; - } + case TCP_SOCKET_STATE_CONNECT_FAILED: { + __wasilibc_poll_ready(state, events); + break; + } - default: - errno = ENOTSUP; - return -1; + default: + errno = ENOTSUP; + return -1; } return 0; } @@ -1185,27 +1222,27 @@ static int tcp_poll_finish(void *data, poll_state_t *state, short events) { } static descriptor_vtable_t tcp_vtable = { - .free = tcp_free, - - .get_read_stream = tcp_get_read_stream, - .get_write_stream = tcp_get_write_stream, - .set_blocking = tcp_set_blocking, - .fstat = tcp_fstat, - - .accept4 = tcp_accept4, - .bind = tcp_bind, - .connect = tcp_connect, - .getsockname = tcp_getsockname, - .getpeername = tcp_getpeername, - .listen = tcp_listen, - .recvfrom = tcp_recvfrom, - .sendto = tcp_sendto, - .shutdown = tcp_shutdown, - .getsockopt = tcp_getsockopt, - .setsockopt = tcp_setsockopt, - - .poll_register = tcp_poll_register, - .poll_finish = tcp_poll_finish, + .free = tcp_free, + + .get_read_stream = tcp_get_read_stream, + .get_write_stream = tcp_get_write_stream, + .set_blocking = tcp_set_blocking, + .fstat = tcp_fstat, + + .accept4 = tcp_accept4, + .bind = tcp_bind, + .connect = tcp_connect, + .getsockname = tcp_getsockname, + .getpeername = tcp_getpeername, + .listen = tcp_listen, + .recvfrom = tcp_recvfrom, + .sendto = tcp_sendto, + .shutdown = tcp_shutdown, + .getsockopt = tcp_getsockopt, + .setsockopt = tcp_setsockopt, + + .poll_register = tcp_poll_register, + .poll_finish = tcp_poll_finish, }; #endif // __wasilibc_use_wasip2 diff --git a/libc-bottom-half/sources/wasip2_udp.c b/libc-bottom-half/sources/wasip2_udp.c index 844343688..fe15c6903 100644 --- a/libc-bottom-half/sources/wasip2_udp.c +++ b/libc-bottom-half/sources/wasip2_udp.c @@ -32,9 +32,11 @@ typedef struct { udp_socket_streams_t streams; // Streams have a remote_address } udp_socket_state_connected_t; -// This is a tagged union. When adding/removing/renaming cases, be sure to keep the tag and union definitions in sync. -// The "bound" state is split up into two distinct tags: -// - "bound_nostreams": Bound, but no datagram streams set up (yet). That will be done the first time send or recv is called. +// This is a tagged union. When adding/removing/renaming cases, be sure to keep +// the tag and union definitions in sync. The "bound" state is split up into two +// distinct tags: +// - "bound_nostreams": Bound, but no datagram streams set up (yet). That will +// be done the first time send or recv is called. // - "bound_streaming": Bound with active streams. typedef struct { enum { @@ -106,7 +108,8 @@ static int udp_create_streams(udp_socket_t *socket, network_error_code_t error; udp_tuple2_own_incoming_datagram_stream_own_outgoing_datagram_stream_t io; - if (!udp_method_udp_socket_stream(socket_borrow, remote_address, &io, &error)) { + if (!udp_method_udp_socket_stream(socket_borrow, remote_address, &io, + &error)) { errno = __wasi_sockets_utils__map_error(error); return -1; } @@ -136,14 +139,14 @@ static void udp_free(void *data) { udp_socket_t *udp = (udp_socket_t *)data; switch (udp->state.tag) { - case UDP_SOCKET_STATE_BOUND_STREAMING: - udp_close_streams(&udp->state.bound_streaming.streams); - break; - case UDP_SOCKET_STATE_CONNECTED: - udp_close_streams(&udp->state.connected.streams); - break; - default: - break; + case UDP_SOCKET_STATE_BOUND_STREAMING: + udp_close_streams(&udp->state.bound_streaming.streams); + break; + case UDP_SOCKET_STATE_CONNECTED: + udp_close_streams(&udp->state.connected.streams); + break; + default: + break; } if (udp->socket_pollable.__handle != 0) @@ -168,30 +171,32 @@ static int udp_fstat(void *data, struct stat *buf) { static poll_borrow_pollable_t udp_pollable(udp_socket_t *socket) { if (socket->socket_pollable.__handle == 0) { - udp_borrow_udp_socket_t socket_borrow = udp_borrow_udp_socket(socket->socket); + udp_borrow_udp_socket_t socket_borrow = + udp_borrow_udp_socket(socket->socket); socket->socket_pollable = udp_method_udp_socket_subscribe(socket_borrow); } return poll_borrow_pollable(socket->socket_pollable); } -static poll_borrow_pollable_t udp_incoming_pollable(udp_socket_streams_t *streams) { +static poll_borrow_pollable_t +udp_incoming_pollable(udp_socket_streams_t *streams) { if (streams->incoming_pollable.__handle == 0) { streams->incoming_pollable = udp_method_incoming_datagram_stream_subscribe( - udp_borrow_incoming_datagram_stream(streams->incoming)); + udp_borrow_incoming_datagram_stream(streams->incoming)); } return poll_borrow_pollable(streams->incoming_pollable); } -static poll_borrow_pollable_t udp_outgoing_pollable(udp_socket_streams_t *streams) { +static poll_borrow_pollable_t +udp_outgoing_pollable(udp_socket_streams_t *streams) { if (streams->outgoing_pollable.__handle == 0) { streams->outgoing_pollable = udp_method_outgoing_datagram_stream_subscribe( - udp_borrow_outgoing_datagram_stream(streams->outgoing)); + udp_borrow_outgoing_datagram_stream(streams->outgoing)); } return poll_borrow_pollable(streams->outgoing_pollable); } -static int udp_handle_error(udp_socket_t *socket, - network_error_code_t error) { +static int udp_handle_error(udp_socket_t *socket, network_error_code_t error) { if (error == NETWORK_ERROR_CODE_WOULD_BLOCK && socket->blocking) { poll_method_pollable_block(udp_pollable(socket)); } else { @@ -202,17 +207,20 @@ static int udp_handle_error(udp_socket_t *socket, return 0; } -static int udp_do_bind(udp_socket_t *socket, network_ip_socket_address_t *address) { +static int udp_do_bind(udp_socket_t *socket, + network_ip_socket_address_t *address) { if (socket->state.tag != UDP_SOCKET_STATE_UNBOUND) { errno = EINVAL; return -1; } network_error_code_t error; - network_borrow_network_t network_borrow = __wasi_sockets_utils__borrow_network(); + network_borrow_network_t network_borrow = + __wasi_sockets_utils__borrow_network(); udp_borrow_udp_socket_t socket_borrow = udp_borrow_udp_socket(socket->socket); - if (!udp_method_udp_socket_start_bind(socket_borrow, network_borrow, address, &error)) { + if (!udp_method_udp_socket_start_bind(socket_borrow, network_borrow, address, + &error)) { errno = __wasi_sockets_utils__map_error(error); return -1; } @@ -228,21 +236,23 @@ static int udp_do_bind(udp_socket_t *socket, network_ip_socket_address_t *addres return 0; } -static int udp_bind(void *data, const struct sockaddr *addr, socklen_t addrlen) { +static int udp_bind(void *data, const struct sockaddr *addr, + socklen_t addrlen) { udp_socket_t *socket = (udp_socket_t *)data; network_ip_socket_address_t local_address; int parse_err; - if (!__wasi_sockets_utils__parse_address(socket->family, addr, addrlen, &local_address, &parse_err)) { + if (!__wasi_sockets_utils__parse_address(socket->family, addr, addrlen, + &local_address, &parse_err)) { errno = parse_err; return -1; } return udp_do_bind(socket, &local_address); } - // When `connect` is called on a UDP socket with an AF_UNSPEC address, it is // actually a "disconnect" request. -static int udp_connect(void *data, const struct sockaddr *addr, socklen_t addrlen) { +static int udp_connect(void *data, const struct sockaddr *addr, + socklen_t addrlen) { udp_socket_t *socket = (udp_socket_t *)data; if (addr == NULL || addrlen < sizeof(struct sockaddr)) { errno = EINVAL; @@ -253,49 +263,53 @@ static int udp_connect(void *data, const struct sockaddr *addr, socklen_t addrle bool has_remote_address = (addr->sa_family != AF_UNSPEC); if (has_remote_address) { int parse_err; - if (!__wasi_sockets_utils__parse_address( - socket->family, addr, addrlen, &remote_address, - &parse_err)) { + if (!__wasi_sockets_utils__parse_address(socket->family, addr, addrlen, + &remote_address, &parse_err)) { errno = parse_err; return -1; } } - // Prepare the socket; binding it if not bound yet, and disconnecting it if connected. + // Prepare the socket; binding it if not bound yet, and disconnecting it if + // connected. switch (socket->state.tag) { - case UDP_SOCKET_STATE_UNBOUND: { - // Socket is not explicitly bound by the user. We'll do it for them: - network_ip_socket_address_t any = __wasi_sockets_utils__any_addr(socket->family); - if (udp_do_bind(socket, &any) < 0) - return -1; - break; - } - case UDP_SOCKET_STATE_BOUND_NOSTREAMS: { - // This is the state we want to be in. - break; - } - case UDP_SOCKET_STATE_BOUND_STREAMING: { - udp_close_streams(&socket->state.bound_streaming.streams); - socket->state.tag = UDP_SOCKET_STATE_BOUND_NOSTREAMS; - break; - } - case UDP_SOCKET_STATE_CONNECTED: { - udp_close_streams(&socket->state.connected.streams); - socket->state.tag = UDP_SOCKET_STATE_BOUND_NOSTREAMS; - break; - } - default: - /* unreachable */ - abort(); + case UDP_SOCKET_STATE_UNBOUND: { + // Socket is not explicitly bound by the user. We'll do it for them: + network_ip_socket_address_t any = + __wasi_sockets_utils__any_addr(socket->family); + if (udp_do_bind(socket, &any) < 0) + return -1; + break; + } + case UDP_SOCKET_STATE_BOUND_NOSTREAMS: { + // This is the state we want to be in. + break; + } + case UDP_SOCKET_STATE_BOUND_STREAMING: { + udp_close_streams(&socket->state.bound_streaming.streams); + socket->state.tag = UDP_SOCKET_STATE_BOUND_NOSTREAMS; + break; + } + case UDP_SOCKET_STATE_CONNECTED: { + udp_close_streams(&socket->state.connected.streams); + socket->state.tag = UDP_SOCKET_STATE_BOUND_NOSTREAMS; + break; + } + default: + /* unreachable */ + abort(); } - return udp_create_streams(socket, has_remote_address ? &remote_address : NULL); + return udp_create_streams(socket, + has_remote_address ? &remote_address : NULL); } -static int udp_getsockname(void *data, struct sockaddr *addr, socklen_t *addrlen) { +static int udp_getsockname(void *data, struct sockaddr *addr, + socklen_t *addrlen) { udp_socket_t *socket = (udp_socket_t *)data; output_sockaddr_t output_addr; - if (!__wasi_sockets_utils__output_addr_validate(socket->family, addr, addrlen, &output_addr)) { + if (!__wasi_sockets_utils__output_addr_validate(socket->family, addr, addrlen, + &output_addr)) { errno = EINVAL; return -1; } @@ -306,18 +320,18 @@ static int udp_getsockname(void *data, struct sockaddr *addr, socklen_t *addrlen } switch (socket->state.tag) { - case UDP_SOCKET_STATE_UNBOUND: - errno = EINVAL; - return -1; + case UDP_SOCKET_STATE_UNBOUND: + errno = EINVAL; + return -1; - case UDP_SOCKET_STATE_BOUND_NOSTREAMS: - case UDP_SOCKET_STATE_BOUND_STREAMING: - case UDP_SOCKET_STATE_CONNECTED: - // OK. Continue.. - break; + case UDP_SOCKET_STATE_BOUND_NOSTREAMS: + case UDP_SOCKET_STATE_BOUND_STREAMING: + case UDP_SOCKET_STATE_CONNECTED: + // OK. Continue.. + break; - default: /* unreachable */ - abort(); + default: /* unreachable */ + abort(); } network_error_code_t error; @@ -332,11 +346,12 @@ static int udp_getsockname(void *data, struct sockaddr *addr, socklen_t *addrlen return 0; } -static int udp_getpeername(void *data, struct sockaddr *addr, socklen_t *addrlen) { - udp_socket_t *socket = (udp_socket_t*) data; +static int udp_getpeername(void *data, struct sockaddr *addr, + socklen_t *addrlen) { + udp_socket_t *socket = (udp_socket_t *)data; output_sockaddr_t output_addr; - if (!__wasi_sockets_utils__output_addr_validate( - socket->family, addr, addrlen, &output_addr)) { + if (!__wasi_sockets_utils__output_addr_validate(socket->family, addr, addrlen, + &output_addr)) { errno = EINVAL; return -1; } @@ -347,18 +362,18 @@ static int udp_getpeername(void *data, struct sockaddr *addr, socklen_t *addrlen } switch (socket->state.tag) { - case UDP_SOCKET_STATE_UNBOUND: - case UDP_SOCKET_STATE_BOUND_NOSTREAMS: - case UDP_SOCKET_STATE_BOUND_STREAMING: - errno = ENOTCONN; - return -1; + case UDP_SOCKET_STATE_UNBOUND: + case UDP_SOCKET_STATE_BOUND_NOSTREAMS: + case UDP_SOCKET_STATE_BOUND_STREAMING: + errno = ENOTCONN; + return -1; - case UDP_SOCKET_STATE_CONNECTED: - // OK. Continue.. - break; + case UDP_SOCKET_STATE_CONNECTED: + // OK. Continue.. + break; - default: /* unreachable */ - abort(); + default: /* unreachable */ + abort(); } network_error_code_t error; @@ -373,13 +388,12 @@ static int udp_getpeername(void *data, struct sockaddr *addr, socklen_t *addrlen return 0; } -static ssize_t udp_recvfrom(void *data, void *buffer, - size_t length, int flags, struct sockaddr *addr, - socklen_t *addrlen) -{ - udp_socket_t *socket = (udp_socket_t*) data; +static ssize_t udp_recvfrom(void *data, void *buffer, size_t length, int flags, + struct sockaddr *addr, socklen_t *addrlen) { + udp_socket_t *socket = (udp_socket_t *)data; // TODO wasi-sockets: flags: - // - MSG_PEEK: could be shimmed by performing the receive into a local socket-specific buffer. And on subsequent receives first check that buffer. + // - MSG_PEEK: could be shimmed by performing the receive into a local + // socket-specific buffer. And on subsequent receives first check that buffer. const int supported_flags = MSG_DONTWAIT | MSG_TRUNC; if ((flags & supported_flags) != flags) { @@ -388,8 +402,8 @@ static ssize_t udp_recvfrom(void *data, void *buffer, } output_sockaddr_t output_addr; - if (!__wasi_sockets_utils__output_addr_validate( - socket->family, addr, addrlen, &output_addr)) { + if (!__wasi_sockets_utils__output_addr_validate(socket->family, addr, addrlen, + &output_addr)) { errno = EINVAL; return -1; } @@ -404,22 +418,22 @@ static ssize_t udp_recvfrom(void *data, void *buffer, udp_socket_streams_t *streams; switch (socket->state.tag) { - case UDP_SOCKET_STATE_UNBOUND: - case UDP_SOCKET_STATE_BOUND_NOSTREAMS: - // Unlike `send`, `recv` should _not_ perform an implicit bind. - errno = EINVAL; - return -1; + case UDP_SOCKET_STATE_UNBOUND: + case UDP_SOCKET_STATE_BOUND_NOSTREAMS: + // Unlike `send`, `recv` should _not_ perform an implicit bind. + errno = EINVAL; + return -1; - case UDP_SOCKET_STATE_BOUND_STREAMING: - streams = &socket->state.bound_streaming.streams; - break; + case UDP_SOCKET_STATE_BOUND_STREAMING: + streams = &socket->state.bound_streaming.streams; + break; - case UDP_SOCKET_STATE_CONNECTED: - streams = &socket->state.connected.streams; - break; + case UDP_SOCKET_STATE_CONNECTED: + streams = &socket->state.connected.streams; + break; - default: /* unreachable */ - abort(); + default: /* unreachable */ + abort(); } bool return_real_size = (flags & MSG_TRUNC) != 0; @@ -429,11 +443,11 @@ static ssize_t udp_recvfrom(void *data, void *buffer, } udp_borrow_incoming_datagram_stream_t incoming_borrow = - udp_borrow_incoming_datagram_stream(streams->incoming); + udp_borrow_incoming_datagram_stream(streams->incoming); while (true) { udp_list_incoming_datagram_t datagrams; - if (!udp_method_incoming_datagram_stream_receive( - incoming_borrow, 1, &datagrams, &error)) { + if (!udp_method_incoming_datagram_stream_receive(incoming_borrow, 1, + &datagrams, &error)) { errno = __wasi_sockets_utils__map_error(error); return -1; } @@ -441,12 +455,11 @@ static ssize_t udp_recvfrom(void *data, void *buffer, if (datagrams.len) { udp_incoming_datagram_t datagram = datagrams.ptr[0]; size_t datagram_size = datagram.data.len; - size_t bytes_to_copy = - datagram_size < length ? datagram_size : length; + size_t bytes_to_copy = datagram_size < length ? datagram_size : length; if (output_addr.tag != OUTPUT_SOCKADDR_NULL) { - __wasi_sockets_utils__output_addr_write( - datagram.remote_address, &output_addr); + __wasi_sockets_utils__output_addr_write(datagram.remote_address, + &output_addr); } memcpy(buffer, datagram.data.ptr, bytes_to_copy); @@ -462,12 +475,10 @@ static ssize_t udp_recvfrom(void *data, void *buffer, } } - -static ssize_t udp_sendto(void *data, const void *buffer, - size_t length, int flags, const struct sockaddr *addr, - socklen_t addrlen) -{ - udp_socket_t *socket = (udp_socket_t*) data; +static ssize_t udp_sendto(void *data, const void *buffer, size_t length, + int flags, const struct sockaddr *addr, + socklen_t addrlen) { + udp_socket_t *socket = (udp_socket_t *)data; const int supported_flags = MSG_DONTWAIT; if ((flags & supported_flags) != flags) { errno = EOPNOTSUPP; @@ -484,9 +495,8 @@ static ssize_t udp_sendto(void *data, const void *buffer, } int parse_err; - if (!__wasi_sockets_utils__parse_address( - socket->family, addr, addrlen, &remote_address, - &parse_err)) { + if (!__wasi_sockets_utils__parse_address(socket->family, addr, addrlen, + &remote_address, &parse_err)) { errno = parse_err; return -1; } @@ -505,10 +515,10 @@ static ssize_t udp_sendto(void *data, const void *buffer, network_error_code_t error; udp_borrow_udp_socket_t socket_borrow = udp_borrow_udp_socket(socket->socket); - // If the socket is not explicitly bound by the user we'll do it for them if (socket->state.tag == UDP_SOCKET_STATE_UNBOUND) { - network_ip_socket_address_t any = __wasi_sockets_utils__any_addr(socket->family); + network_ip_socket_address_t any = + __wasi_sockets_utils__any_addr(socket->family); if (udp_do_bind(socket, &any) < 0) return -1; } @@ -520,21 +530,21 @@ static ssize_t udp_sendto(void *data, const void *buffer, udp_socket_streams_t *streams; switch (socket->state.tag) { - case UDP_SOCKET_STATE_UNBOUND: - case UDP_SOCKET_STATE_BOUND_NOSTREAMS: - errno = EINVAL; - return -1; + case UDP_SOCKET_STATE_UNBOUND: + case UDP_SOCKET_STATE_BOUND_NOSTREAMS: + errno = EINVAL; + return -1; - case UDP_SOCKET_STATE_BOUND_STREAMING: - streams = &socket->state.bound_streaming.streams; - break; + case UDP_SOCKET_STATE_BOUND_STREAMING: + streams = &socket->state.bound_streaming.streams; + break; - case UDP_SOCKET_STATE_CONNECTED: - streams = &socket->state.connected.streams; - break; + case UDP_SOCKET_STATE_CONNECTED: + streams = &socket->state.connected.streams; + break; - default: /* unreachable */ - abort(); + default: /* unreachable */ + abort(); } bool should_block = socket->blocking; @@ -543,35 +553,36 @@ static ssize_t udp_sendto(void *data, const void *buffer, } udp_outgoing_datagram_t datagrams[1] = {{ - .remote_address = { - .is_some = has_remote_address, - .val = remote_address, - }, - .data = { - .len = length, - .ptr = (uint8_t*)buffer, - }, + .remote_address = + { + .is_some = has_remote_address, + .val = remote_address, + }, + .data = + { + .len = length, + .ptr = (uint8_t *)buffer, + }, }}; udp_list_outgoing_datagram_t list = { - .len = 1, - .ptr = datagrams, + .len = 1, + .ptr = datagrams, }; udp_borrow_outgoing_datagram_stream_t outgoing_borrow = - udp_borrow_outgoing_datagram_stream(streams->outgoing); + udp_borrow_outgoing_datagram_stream(streams->outgoing); while (true) { uint64_t allowed; - if (!udp_method_outgoing_datagram_stream_check_send( - outgoing_borrow, &allowed, &error)) { + if (!udp_method_outgoing_datagram_stream_check_send(outgoing_borrow, + &allowed, &error)) { errno = __wasi_sockets_utils__map_error(error); return -1; } if (allowed) { uint64_t datagrams_sent; - if (!udp_method_outgoing_datagram_stream_send( - outgoing_borrow, &list, &datagrams_sent, - &error)) { + if (!udp_method_outgoing_datagram_stream_send(outgoing_borrow, &list, + &datagrams_sent, &error)) { errno = __wasi_sockets_utils__map_error(error); return -1; } @@ -593,119 +604,118 @@ static ssize_t udp_sendto(void *data, const void *buffer, } } -static int udp_getsockopt(void *data, int level, int optname, - void *optval, socklen_t *optlen) -{ - udp_socket_t *socket = (udp_socket_t*) data; +static int udp_getsockopt(void *data, int level, int optname, void *optval, + socklen_t *optlen) { + udp_socket_t *socket = (udp_socket_t *)data; int value; network_error_code_t error; udp_borrow_udp_socket_t socket_borrow = udp_borrow_udp_socket(socket->socket); switch (level) { - case SOL_SOCKET: - switch (optname) { - case SO_TYPE: { - value = SOCK_DGRAM; - break; - } - case SO_PROTOCOL: { - value = IPPROTO_UDP; - break; - } - case SO_DOMAIN: { - value = __wasi_sockets_utils__posix_family(socket->family); - break; - } - case SO_RCVBUF: { - uint64_t result; - if (!udp_method_udp_socket_receive_buffer_size( - socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - if (result > INT_MAX) { - abort(); - } - - value = result; - break; - } - case SO_SNDBUF: { - uint64_t result; - if (!udp_method_udp_socket_send_buffer_size( - socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - if (result > INT_MAX) { - abort(); - } - - value = result; - break; - } - case SO_RCVTIMEO: // TODO wasi-sockets: emulate in wasi-libc itself - case SO_SNDTIMEO: // TODO wasi-sockets: emulate in wasi-libc itself - default: - errno = ENOPROTOOPT; - return -1; + case SOL_SOCKET: + switch (optname) { + case SO_TYPE: { + value = SOCK_DGRAM; + break; + } + case SO_PROTOCOL: { + value = IPPROTO_UDP; + break; + } + case SO_DOMAIN: { + value = __wasi_sockets_utils__posix_family(socket->family); + break; + } + case SO_RCVBUF: { + uint64_t result; + if (!udp_method_udp_socket_receive_buffer_size(socket_borrow, &result, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + if (result > INT_MAX) { + abort(); } + + value = result; break; + } + case SO_SNDBUF: { + uint64_t result; + if (!udp_method_udp_socket_send_buffer_size(socket_borrow, &result, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } - case SOL_IP: - switch (optname) { - case IP_TTL: { - if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV4) { - errno = EAFNOSUPPORT; - return -1; - } - - uint8_t result; - if (!udp_method_udp_socket_unicast_hop_limit( - socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - value = result; - break; - } - default: - errno = ENOPROTOOPT; - return -1; + if (result > INT_MAX) { + abort(); } + + value = result; break; + } + case SO_RCVTIMEO: // TODO wasi-sockets: emulate in wasi-libc itself + case SO_SNDTIMEO: // TODO wasi-sockets: emulate in wasi-libc itself + default: + errno = ENOPROTOOPT; + return -1; + } + break; - case SOL_IPV6: - switch (optname) { - case IPV6_UNICAST_HOPS: { - if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV6) { - errno = EAFNOSUPPORT; - return -1; - } - - uint8_t result; - if (!udp_method_udp_socket_unicast_hop_limit( - socket_borrow, &result, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - value = result; - break; - } - default: - errno = ENOPROTOOPT; - return -1; + case SOL_IP: + switch (optname) { + case IP_TTL: { + if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV4) { + errno = EAFNOSUPPORT; + return -1; } + + uint8_t result; + if (!udp_method_udp_socket_unicast_hop_limit(socket_borrow, &result, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + value = result; break; + } + default: + errno = ENOPROTOOPT; + return -1; + } + break; + + case SOL_IPV6: + switch (optname) { + case IPV6_UNICAST_HOPS: { + if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV6) { + errno = EAFNOSUPPORT; + return -1; + } + + uint8_t result; + if (!udp_method_udp_socket_unicast_hop_limit(socket_borrow, &result, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + value = result; + break; + } default: errno = ENOPROTOOPT; return -1; + } + break; + + default: + errno = ENOPROTOOPT; + return -1; } // Copy out integer value. @@ -715,155 +725,153 @@ static int udp_getsockopt(void *data, int level, int optname, } static int udp_setsockopt(void *data, int level, int optname, - const void *optval, socklen_t optlen) -{ - udp_socket_t *socket = (udp_socket_t*) data; + const void *optval, socklen_t optlen) { + udp_socket_t *socket = (udp_socket_t *)data; int intval = *(int *)optval; network_error_code_t error; - udp_borrow_udp_socket_t socket_borrow = - udp_borrow_udp_socket(socket->socket); + udp_borrow_udp_socket_t socket_borrow = udp_borrow_udp_socket(socket->socket); switch (level) { - case SOL_SOCKET: - switch (optname) { - case SO_RCVBUF: { - if (!udp_method_udp_socket_set_receive_buffer_size( - socket_borrow, intval, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - case SO_SNDBUF: { - if (!udp_method_udp_socket_set_send_buffer_size( - socket_borrow, intval, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - case SO_RCVTIMEO: // TODO wasi-sockets: emulate in wasi-libc itself - case SO_SNDTIMEO: // TODO wasi-sockets: emulate in wasi-libc itself - default: - errno = ENOPROTOOPT; - return -1; + case SOL_SOCKET: + switch (optname) { + case SO_RCVBUF: { + if (!udp_method_udp_socket_set_receive_buffer_size(socket_borrow, intval, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; } - break; - case SOL_IP: - switch (optname) { - case IP_TTL: { - if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV4) { - errno = EAFNOSUPPORT; - return -1; - } - - if (intval < 0 || intval > UINT8_MAX) { - errno = EINVAL; - return -1; - } - - if (!udp_method_udp_socket_set_unicast_hop_limit( - socket_borrow, intval, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - default: - errno = ENOPROTOOPT; - return -1; + return 0; + } + case SO_SNDBUF: { + if (!udp_method_udp_socket_set_send_buffer_size(socket_borrow, intval, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; } - break; - case SOL_IPV6: - switch (optname) { - case IPV6_UNICAST_HOPS: { - if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV6) { - errno = EAFNOSUPPORT; - return -1; - } - - if (intval < 0 || intval > UINT8_MAX) { - errno = EINVAL; - return -1; - } - - if (!udp_method_udp_socket_set_unicast_hop_limit( - socket_borrow, intval, &error)) { - errno = __wasi_sockets_utils__map_error(error); - return -1; - } - - return 0; - } - default: - errno = ENOPROTOOPT; - return -1; + return 0; + } + case SO_RCVTIMEO: // TODO wasi-sockets: emulate in wasi-libc itself + case SO_SNDTIMEO: // TODO wasi-sockets: emulate in wasi-libc itself + default: + errno = ENOPROTOOPT; + return -1; + } + break; + + case SOL_IP: + switch (optname) { + case IP_TTL: { + if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV4) { + errno = EAFNOSUPPORT; + return -1; } - break; + if (intval < 0 || intval > UINT8_MAX) { + errno = EINVAL; + return -1; + } + + if (!udp_method_udp_socket_set_unicast_hop_limit(socket_borrow, intval, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; + } + + return 0; + } default: errno = ENOPROTOOPT; return -1; - } -} - -static int udp_poll_register(void *data, - poll_state_t *state, - short events) { - udp_socket_t *socket = (udp_socket_t *)data; - switch (socket->state.tag) { - case UDP_SOCKET_STATE_UNBOUND: - case UDP_SOCKET_STATE_BOUND_NOSTREAMS: - __wasilibc_poll_ready(state, events); - break; + } + break; - case UDP_SOCKET_STATE_BOUND_STREAMING: - case UDP_SOCKET_STATE_CONNECTED: { - udp_socket_streams_t *streams; - if (socket->state.tag == UDP_SOCKET_STATE_BOUND_STREAMING) { - streams = &socket->state.bound_streaming.streams; - } else { - streams = &socket->state.connected.streams; + case SOL_IPV6: + switch (optname) { + case IPV6_UNICAST_HOPS: { + if (socket->family != NETWORK_IP_ADDRESS_FAMILY_IPV6) { + errno = EAFNOSUPPORT; + return -1; } - if ((events & POLLRDNORM) != 0) { - if (__wasilibc_poll_add(state, POLLRDNORM, udp_incoming_pollable(streams)) < 0) - return -1; + + if (intval < 0 || intval > UINT8_MAX) { + errno = EINVAL; + return -1; } - if ((events & POLLWRNORM) != 0) { - if (__wasilibc_poll_add(state, POLLWRNORM, udp_outgoing_pollable(streams)) < 0) - return -1; + + if (!udp_method_udp_socket_set_unicast_hop_limit(socket_borrow, intval, + &error)) { + errno = __wasi_sockets_utils__map_error(error); + return -1; } - break; + + return 0; } default: - errno = ENOTSUP; + errno = ENOPROTOOPT; return -1; + } + break; + + default: + errno = ENOPROTOOPT; + return -1; + } +} + +static int udp_poll_register(void *data, poll_state_t *state, short events) { + udp_socket_t *socket = (udp_socket_t *)data; + switch (socket->state.tag) { + case UDP_SOCKET_STATE_UNBOUND: + case UDP_SOCKET_STATE_BOUND_NOSTREAMS: + __wasilibc_poll_ready(state, events); + break; + + case UDP_SOCKET_STATE_BOUND_STREAMING: + case UDP_SOCKET_STATE_CONNECTED: { + udp_socket_streams_t *streams; + if (socket->state.tag == UDP_SOCKET_STATE_BOUND_STREAMING) { + streams = &socket->state.bound_streaming.streams; + } else { + streams = &socket->state.connected.streams; + } + if ((events & POLLRDNORM) != 0) { + if (__wasilibc_poll_add(state, POLLRDNORM, + udp_incoming_pollable(streams)) < 0) + return -1; + } + if ((events & POLLWRNORM) != 0) { + if (__wasilibc_poll_add(state, POLLWRNORM, + udp_outgoing_pollable(streams)) < 0) + return -1; + } + break; + } + default: + errno = ENOTSUP; + return -1; } return 0; } static descriptor_vtable_t udp_vtable = { - .free = udp_free, + .free = udp_free, - .set_blocking = udp_set_blocking, - .fstat = udp_fstat, + .set_blocking = udp_set_blocking, + .fstat = udp_fstat, - .bind = udp_bind, - .connect = udp_connect, - .getsockname = udp_getsockname, - .getpeername = udp_getpeername, - .recvfrom = udp_recvfrom, - .sendto = udp_sendto, - .getsockopt = udp_getsockopt, - .setsockopt = udp_setsockopt, + .bind = udp_bind, + .connect = udp_connect, + .getsockname = udp_getsockname, + .getpeername = udp_getpeername, + .recvfrom = udp_recvfrom, + .sendto = udp_sendto, + .getsockopt = udp_getsockopt, + .setsockopt = udp_setsockopt, - .poll_register = udp_poll_register, + .poll_register = udp_poll_register, }; #endif // __wasilibc_use_wasip2 diff --git a/test/src/busywait.c b/test/src/busywait.c index a56484558..65c1ce846 100644 --- a/test/src/busywait.c +++ b/test/src/busywait.c @@ -1,27 +1,27 @@ #include +#include #include #include -#include #include static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; int main() { - struct timespec ts; - int ret; + struct timespec ts; + int ret; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += 1; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 1; - __wasilibc_enable_futex_busywait_on_current_thread(); + __wasilibc_enable_futex_busywait_on_current_thread(); - pthread_mutex_lock(&mutex); + pthread_mutex_lock(&mutex); - ret = pthread_cond_timedwait(&cond, &mutex, &ts); + ret = pthread_cond_timedwait(&cond, &mutex, &ts); - assert(ret == ETIMEDOUT); + assert(ret == ETIMEDOUT); - pthread_mutex_unlock(&mutex); - return 0; + pthread_mutex_unlock(&mutex); + return 0; } diff --git a/test/src/poll-nonblocking-socket.c b/test/src/poll-nonblocking-socket.c index 9733f6232..105a091f4 100644 --- a/test/src/poll-nonblocking-socket.c +++ b/test/src/poll-nonblocking-socket.c @@ -1,58 +1,61 @@ +#include "test.h" +#include #include #include +#include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; // See sockets-server.c -- must be running already as a separate executable void test_tcp_client() { - // Prepare client socket - int socket_fd = socket(AF_INET, SOCK_STREAM, 0); - TEST(socket_fd != -1); - - int server_port = 4001; - - // Check that if a non-blocking socket is in progress, poll() indicates the right result - socket_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); - struct sockaddr_in sockaddr_in; - // Doesn't matter what address we connect to, since we only attempt to connect once - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); - TEST(socket_fd != -1); - int connect_result = connect(socket_fd, (const struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)); - TEST(connect_result == -1); - - // Poll the socket for writability - struct pollfd poll_fd = { .fd = socket_fd, .events = POLLWRNORM, .revents = 0 }; - poll(&poll_fd, 1, 10); - - // Socket should not be writable - int32_t error = -1; - socklen_t len = -1; - TEST(getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0); - TEST(error == ECONNREFUSED); - close(socket_fd); + // Prepare client socket + int socket_fd = socket(AF_INET, SOCK_STREAM, 0); + TEST(socket_fd != -1); + + int server_port = 4001; + + // Check that if a non-blocking socket is in progress, poll() indicates the + // right result + socket_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + struct sockaddr_in sockaddr_in; + // Doesn't matter what address we connect to, since we only attempt to connect + // once + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); + TEST(socket_fd != -1); + int connect_result = connect(socket_fd, (const struct sockaddr *)&sockaddr_in, + sizeof(sockaddr_in)); + TEST(connect_result == -1); + + // Poll the socket for writability + struct pollfd poll_fd = {.fd = socket_fd, .events = POLLWRNORM, .revents = 0}; + poll(&poll_fd, 1, 10); + + // Socket should not be writable + int32_t error = -1; + socklen_t len = -1; + TEST(getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0); + TEST(error == ECONNREFUSED); + close(socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/pthread_cond_busywait.c b/test/src/pthread_cond_busywait.c index fd0f5dd0b..b10b07c89 100644 --- a/test/src/pthread_cond_busywait.c +++ b/test/src/pthread_cond_busywait.c @@ -2,8 +2,6 @@ #include -__attribute__((constructor)) -void __wasilibc_enable_busywait(void) -{ - __wasilibc_enable_futex_busywait_on_current_thread(); +__attribute__((constructor)) void __wasilibc_enable_busywait(void) { + __wasilibc_enable_futex_busywait_on_current_thread(); } diff --git a/test/src/pthread_mutex_busywait.c b/test/src/pthread_mutex_busywait.c index 184f1be7a..82f9d7d65 100644 --- a/test/src/pthread_mutex_busywait.c +++ b/test/src/pthread_mutex_busywait.c @@ -2,8 +2,6 @@ #include -__attribute__((constructor)) -void __wasilibc_enable_busywait(void) -{ - __wasilibc_enable_futex_busywait_on_current_thread(); +__attribute__((constructor)) void __wasilibc_enable_busywait(void) { + __wasilibc_enable_futex_busywait_on_current_thread(); } diff --git a/test/src/pthread_tsd_busywait.c b/test/src/pthread_tsd_busywait.c index 688e6c359..6988ad78b 100644 --- a/test/src/pthread_tsd_busywait.c +++ b/test/src/pthread_tsd_busywait.c @@ -2,8 +2,6 @@ #include -__attribute__((constructor)) -void __wasilibc_enable_busywait(void) -{ - __wasilibc_enable_futex_busywait_on_current_thread(); +__attribute__((constructor)) void __wasilibc_enable_busywait(void) { + __wasilibc_enable_futex_busywait_on_current_thread(); } diff --git a/test/src/setsockopt.c b/test/src/setsockopt.c index e40ee69a1..df3c5550b 100644 --- a/test/src/setsockopt.c +++ b/test/src/setsockopt.c @@ -1,77 +1,85 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; // See sockets-server.c -- must be running already as a separate executable void test_tcp_client() { - // Prepare client socket - int socket_fd = socket(AF_INET, SOCK_STREAM, 0); - TEST(socket_fd != -1); + // Prepare client socket + int socket_fd = socket(AF_INET, SOCK_STREAM, 0); + TEST(socket_fd != -1); - // Set send timeout to 3 and let recv timeout default to 0; test that getsockopt() returns the right results - struct timeval tv = { .tv_sec = 3, .tv_usec = 0 }; - socklen_t len = sizeof(tv); - TEST(setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv))==0); - TEST(getsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len)==0); - TEST(tv.tv_sec == 0); - TEST(tv.tv_usec == 0); - TEST(len == sizeof(tv)); - TEST(getsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &len)==0); - TEST(tv.tv_sec == 3); - TEST(tv.tv_usec == 0); - TEST(len == sizeof(tv)); + // Set send timeout to 3 and let recv timeout default to 0; test that + // getsockopt() returns the right results + struct timeval tv = {.tv_sec = 3, .tv_usec = 0}; + socklen_t len = sizeof(tv); + TEST(setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, + sizeof(tv)) == 0); + TEST(getsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len) == 0); + TEST(tv.tv_sec == 0); + TEST(tv.tv_usec == 0); + TEST(len == sizeof(tv)); + TEST(getsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &len) == 0); + TEST(tv.tv_sec == 3); + TEST(tv.tv_usec == 0); + TEST(len == sizeof(tv)); - // Set send timeout to 0 and recv timeout to 3; test that getsockopt() returns the right results - tv.tv_sec = 0; - TEST(setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv))==0); - tv.tv_sec = 3; - TEST(setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv))==0); - TEST(getsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len)==0); - TEST(tv.tv_sec == 3); - TEST(tv.tv_usec == 0); - TEST(len == sizeof(tv)); - TEST(getsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &len)==0); - TEST(tv.tv_sec == 0); - TEST(tv.tv_usec == 0); - TEST(len == sizeof(tv)); + // Set send timeout to 0 and recv timeout to 3; test that getsockopt() returns + // the right results + tv.tv_sec = 0; + TEST(setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, + sizeof(tv)) == 0); + tv.tv_sec = 3; + TEST(setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, + sizeof(tv)) == 0); + TEST(getsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len) == 0); + TEST(tv.tv_sec == 3); + TEST(tv.tv_usec == 0); + TEST(len == sizeof(tv)); + TEST(getsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &len) == 0); + TEST(tv.tv_sec == 0); + TEST(tv.tv_usec == 0); + TEST(len == sizeof(tv)); - // Set send timeout to 1 and recv timeout to 2; test that getsockopt() returns the right results - tv.tv_sec = 1; - TEST(setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv))==0); - tv.tv_sec = 2; - TEST(setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv))==0); - TEST(getsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len)==0); - TEST(tv.tv_sec == 2); - TEST(tv.tv_usec == 0); - TEST(len == sizeof(tv)); - TEST(getsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &len)==0); - TEST(tv.tv_sec == 1); - TEST(tv.tv_usec == 0); - TEST(len == sizeof(tv)); + // Set send timeout to 1 and recv timeout to 2; test that getsockopt() returns + // the right results + tv.tv_sec = 1; + TEST(setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, + sizeof(tv)) == 0); + tv.tv_sec = 2; + TEST(setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, + sizeof(tv)) == 0); + TEST(getsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len) == 0); + TEST(tv.tv_sec == 2); + TEST(tv.tv_usec == 0); + TEST(len == sizeof(tv)); + TEST(getsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &len) == 0); + TEST(tv.tv_sec == 1); + TEST(tv.tv_usec == 0); + TEST(len == sizeof(tv)); - // Shut down client - close(socket_fd); + // Shut down client + close(socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-client-handle-hangups.c b/test/src/sockets-client-handle-hangups.c index 90390c96a..8f8fbab9c 100644 --- a/test/src/sockets-client-handle-hangups.c +++ b/test/src/sockets-client-handle-hangups.c @@ -1,20 +1,21 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; @@ -33,49 +34,48 @@ static int wait_for_server(struct sockaddr_in *addr) { // Server must be running already as a separate executable // (except when testing the case where connect() fails) void test_tcp_client() { - // Prepare server socket - int server_port = 4001; + // Prepare server socket + int server_port = 4001; - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); - // Connect from client - char message[] = "There's gonna be a party when the wolf comes home"; - int len = strlen(message); - char client_buffer[BUFSIZE]; + // Connect from client + char message[] = "There's gonna be a party when the wolf comes home"; + int len = strlen(message); + char client_buffer[BUFSIZE]; - int socket_fd = wait_for_server(&sockaddr_in); - if (socket_fd == -1) - return; + int socket_fd = wait_for_server(&sockaddr_in); + if (socket_fd == -1) + return; - // Client writes a message to server - // This should succeed even in the presence of hangups, - // since send() only fails if there's a local error - TEST(send(socket_fd, message, len, 0) == len); + // Client writes a message to server + // This should succeed even in the presence of hangups, + // since send() only fails if there's a local error + TEST(send(socket_fd, message, len, 0) == len); - // Set timeout for recv - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 500000; // 500 milliseconds - setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)); + // Set timeout for recv + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 500000; // 500 milliseconds + setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)); - // Client reads from server - int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); - if (bytes_received == len) { - // Message received should be the same as message sent - TEST(strcmp(message, client_buffer) == 0); - } + // Client reads from server + int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); + if (bytes_received == len) { + // Message received should be the same as message sent + TEST(strcmp(message, client_buffer) == 0); + } - // Shut down client - close(socket_fd); + // Shut down client + close(socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-client-hangup-after-connect.c b/test/src/sockets-client-hangup-after-connect.c index d1f86507e..c2e713411 100644 --- a/test/src/sockets-client-hangup-after-connect.c +++ b/test/src/sockets-client-hangup-after-connect.c @@ -1,20 +1,21 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; @@ -27,32 +28,31 @@ static int wait_for_server(struct sockaddr_in *addr) { close(fd); usleep(5000); // sleep for 5ms } - t_error("server didn't come online within 1 second (errno = %d)\n", errno); \ + t_error("server didn't come online within 1 second (errno = %d)\n", errno); return -1; } // Server must be running already as a separate executable // (except when testing the case where connect() fails) void test_tcp_client() { - // Prepare server socket - int server_port = 4001; + // Prepare server socket + int server_port = 4001; - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); - // Connect from client - int socket_fd = wait_for_server(&sockaddr_in); + // Connect from client + int socket_fd = wait_for_server(&sockaddr_in); - // Hang up immediately - close(socket_fd); + // Hang up immediately + close(socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-client-hangup-after-sending.c b/test/src/sockets-client-hangup-after-sending.c index 5af7c9975..bf9e1431c 100644 --- a/test/src/sockets-client-hangup-after-sending.c +++ b/test/src/sockets-client-hangup-after-sending.c @@ -1,20 +1,21 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; @@ -27,38 +28,37 @@ static int wait_for_server(struct sockaddr_in *addr) { close(fd); usleep(5000); // sleep for 5ms } - t_error("server didn't come online within 1 second (errno = %d)\n", errno); \ + t_error("server didn't come online within 1 second (errno = %d)\n", errno); return -1; } // See sockets-server.c -- must be running already as a separate executable void test_tcp_client() { - // Prepare server socket - int server_port = 4001; + // Prepare server socket + int server_port = 4001; - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); - // Connect from client - char message[] = "There's gonna be a party when the wolf comes home"; - int len = strlen(message); - char client_buffer[BUFSIZE]; + // Connect from client + char message[] = "There's gonna be a party when the wolf comes home"; + int len = strlen(message); + char client_buffer[BUFSIZE]; - int socket_fd = wait_for_server(&sockaddr_in); + int socket_fd = wait_for_server(&sockaddr_in); - // Client writes a message to server - TEST(send(socket_fd, message, len, 0) == len); + // Client writes a message to server + TEST(send(socket_fd, message, len, 0) == len); - // Shut down client - close(socket_fd); + // Shut down client + close(socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-client-hangup-while-receiving.c b/test/src/sockets-client-hangup-while-receiving.c index 646bc2419..1477a7123 100644 --- a/test/src/sockets-client-hangup-while-receiving.c +++ b/test/src/sockets-client-hangup-while-receiving.c @@ -1,20 +1,21 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; @@ -27,45 +28,45 @@ static int wait_for_server(struct sockaddr_in *addr) { close(fd); usleep(5000); // sleep for 5ms } - t_error("server didn't come online within 1 second (errno = %d)\n", errno); \ + t_error("server didn't come online within 1 second (errno = %d)\n", errno); return -1; } // See sockets-server.c -- must be running already as a separate executable void test_tcp_client() { - // Prepare server socket - int server_port = 4001; + // Prepare server socket + int server_port = 4001; - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); - // Connect from client - char message[] = "There's gonna be a party when the wolf comes home"; - int len = strlen(message); - char client_buffer[BUFSIZE]; + // Connect from client + char message[] = "There's gonna be a party when the wolf comes home"; + int len = strlen(message); + char client_buffer[BUFSIZE]; - int socket_fd = wait_for_server(&sockaddr_in); + int socket_fd = wait_for_server(&sockaddr_in); - // Client writes a message to server - TEST(send(socket_fd, message, len, 0) == len); + // Client writes a message to server + TEST(send(socket_fd, message, len, 0) == len); - // Set timeout to 2 us so that client will hang up while receiving - struct timeval tv = { .tv_sec = 0, .tv_usec = 2 }; - TEST(setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv))==0); + // Set timeout to 2 us so that client will hang up while receiving + struct timeval tv = {.tv_sec = 0, .tv_usec = 2}; + TEST(setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, + sizeof(tv)) == 0); - // Client reads from server - int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); + // Client reads from server + int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); - // Shut down client - close(socket_fd); + // Shut down client + close(socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-client-hangup-while-sending.c b/test/src/sockets-client-hangup-while-sending.c index b3b24f271..dccbd7048 100644 --- a/test/src/sockets-client-hangup-while-sending.c +++ b/test/src/sockets-client-hangup-while-sending.c @@ -1,20 +1,21 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; @@ -27,42 +28,42 @@ static int wait_for_server(struct sockaddr_in *addr) { close(fd); usleep(5000); // sleep for 5ms } - t_error("server didn't come online within 1 second (errno = %d)\n", errno); \ + t_error("server didn't come online within 1 second (errno = %d)\n", errno); return -1; } // See sockets-server.c -- must be running already as a separate executable void test_tcp_client() { - // Prepare server socket - int server_port = 4001; + // Prepare server socket + int server_port = 4001; - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); - // Connect from client - char message[] = "There's gonna be a party when the wolf comes home"; - int len = strlen(message); - char client_buffer[BUFSIZE]; + // Connect from client + char message[] = "There's gonna be a party when the wolf comes home"; + int len = strlen(message); + char client_buffer[BUFSIZE]; - int socket_fd = wait_for_server(&sockaddr_in); + int socket_fd = wait_for_server(&sockaddr_in); - // Set the timeout to 2 us so that it should time out while sending - struct timeval tv = { .tv_sec = 0, .tv_usec = 2 }; - TEST(setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv))==0); + // Set the timeout to 2 us so that it should time out while sending + struct timeval tv = {.tv_sec = 0, .tv_usec = 2}; + TEST(setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, + sizeof(tv)) == 0); - // Client writes a message to server - TEST(send(socket_fd, message, len, 0) == len); + // Client writes a message to server + TEST(send(socket_fd, message, len, 0) == len); - // Shut down client - close(socket_fd); + // Shut down client + close(socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-client-udp-blocking.c b/test/src/sockets-client-udp-blocking.c index f192a0e5e..c421a0261 100644 --- a/test/src/sockets-client-udp-blocking.c +++ b/test/src/sockets-client-udp-blocking.c @@ -1,20 +1,21 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; @@ -27,54 +28,55 @@ static int wait_for_server(struct sockaddr_in *addr) { close(fd); usleep(5000); // sleep for 5ms } - t_error("server didn't come online within 1 second (errno = %d)\n", errno); \ + t_error("server didn't come online within 1 second (errno = %d)\n", errno); return -1; } -// See sockets-server-udp-blocking.c -- must be running already as a separate executable +// See sockets-server-udp-blocking.c -- must be running already as a separate +// executable void test_udp_client() { - // Prepare server socket - int server_port = 4001; + // Prepare server socket + int server_port = 4001; - // Prepare client socket - // Use blocking sockets - int socket_fd = socket(AF_INET, SOCK_DGRAM, 0); - TEST(socket_fd != -1); + // Prepare client socket + // Use blocking sockets + int socket_fd = socket(AF_INET, SOCK_DGRAM, 0); + TEST(socket_fd != -1); - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); - // Synchronize the UDP port being bound by waiting for a TCP connection to - // go through. - close(wait_for_server(&sockaddr_in)); + // Synchronize the UDP port being bound by waiting for a TCP connection to + // go through. + close(wait_for_server(&sockaddr_in)); - // Connect from client - char message[] = "There's gonna be a party when the wolf comes home"; - int len = strlen(message); - char client_buffer[BUFSIZE]; + // Connect from client + char message[] = "There's gonna be a party when the wolf comes home"; + int len = strlen(message); + char client_buffer[BUFSIZE]; - TEST(connect(socket_fd, (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in)) != -1); + TEST(connect(socket_fd, (struct sockaddr *)&sockaddr_in, + sizeof(sockaddr_in)) != -1); - // Client writes a message to server - TEST(send(socket_fd, message, len, 0) == len); + // Client writes a message to server + TEST(send(socket_fd, message, len, 0) == len); - // Client reads from server - int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); - TEST(bytes_received == len); + // Client reads from server + int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); + TEST(bytes_received == len); - // Message received should be the same as message sent - TEST(strncmp(message, client_buffer, len) == 0); + // Message received should be the same as message sent + TEST(strncmp(message, client_buffer, len) == 0); - // Shut down client - close(socket_fd); + // Shut down client + close(socket_fd); } -int main(void) -{ - test_udp_client(); +int main(void) { + test_udp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-client.c b/test/src/sockets-client.c index 7d38d7c3d..c325be692 100644 --- a/test/src/sockets-client.c +++ b/test/src/sockets-client.c @@ -1,20 +1,21 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; @@ -27,48 +28,47 @@ static int wait_for_server(struct sockaddr_in *addr) { close(fd); usleep(5000); // sleep for 5ms } - t_error("server didn't come online within 1 second (errno = %d)\n", errno); \ + t_error("server didn't come online within 1 second (errno = %d)\n", errno); return -1; } // See sockets-server.c -- must be running already as a separate executable void test_tcp_client() { - // Prepare server socket - int server_port = 4001; + // Prepare server socket + int server_port = 4001; - // Prepare client socket - // Use blocking sockets + // Prepare client socket + // Use blocking sockets - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); - // Connect from client - char message[] = "There's gonna be a party when the wolf comes home"; - int len = strlen(message); - char client_buffer[BUFSIZE]; + // Connect from client + char message[] = "There's gonna be a party when the wolf comes home"; + int len = strlen(message); + char client_buffer[BUFSIZE]; - int socket_fd = wait_for_server(&sockaddr_in); + int socket_fd = wait_for_server(&sockaddr_in); - // Client writes a message to server - TEST(send(socket_fd, message, len, 0) == len); + // Client writes a message to server + TEST(send(socket_fd, message, len, 0) == len); - // Client reads from server - int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); - TEST(bytes_received == len); + // Client reads from server + int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); + TEST(bytes_received == len); - // Message received should be the same as message sent - TEST(strcmp(message, client_buffer) == 0); + // Message received should be the same as message sent + TEST(strcmp(message, client_buffer) == 0); - // Shut down client - close(socket_fd); + // Shut down client + close(socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-multiple-client.c b/test/src/sockets-multiple-client.c index 6f56f74f4..711c4be3b 100644 --- a/test/src/sockets-multiple-client.c +++ b/test/src/sockets-multiple-client.c @@ -1,20 +1,21 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; @@ -27,51 +28,51 @@ static int wait_for_server(struct sockaddr_in *addr) { close(fd); usleep(5000); // sleep for 5ms } - t_error("server didn't come online within 1 second (errno = %d)\n", errno); \ + t_error("server didn't come online within 1 second (errno = %d)\n", errno); return -1; } -// See sockets-multiple-server.c -- must be running already as a separate executable +// See sockets-multiple-server.c -- must be running already as a separate +// executable void test_tcp_client() { - // Prepare server socket - int server_port = 4001; + // Prepare server socket + int server_port = 4001; - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); - // Connect from client - // Generate a random number to test that multiple clients each receive - // the correct response - int32_t number = 0; - getentropy(&number, sizeof(int32_t)); - char message[BUFSIZE]; - sprintf(message, "%d", number); - int len = strlen(message); - char client_buffer[BUFSIZE]; + // Connect from client + // Generate a random number to test that multiple clients each receive + // the correct response + int32_t number = 0; + getentropy(&number, sizeof(int32_t)); + char message[BUFSIZE]; + sprintf(message, "%d", number); + int len = strlen(message); + char client_buffer[BUFSIZE]; - int socket_fd = wait_for_server(&sockaddr_in); + int socket_fd = wait_for_server(&sockaddr_in); - // Client writes a message to server - TEST(send(socket_fd, message, len, 0) == len); + // Client writes a message to server + TEST(send(socket_fd, message, len, 0) == len); - // Client reads from server - int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); - TEST(bytes_received == len); - client_buffer[len] = 0; + // Client reads from server + int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); + TEST(bytes_received == len); + client_buffer[len] = 0; - // Message received should be the same as message sent - TEST(strcmp(message, client_buffer) == 0); + // Message received should be the same as message sent + TEST(strcmp(message, client_buffer) == 0); - // Shut down client - close(socket_fd); + // Shut down client + close(socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-multiple-server.c b/test/src/sockets-multiple-server.c index 497078709..863e2f30a 100644 --- a/test/src/sockets-multiple-server.c +++ b/test/src/sockets-multiple-server.c @@ -1,95 +1,97 @@ +#include "poll.h" +#include "test.h" +#include #include #include +#include +#include #include #include #include #include -#include -#include #include -#include -#include -#include "poll.h" -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; int EXPECTED_CONNECTIONS = 10; int TIMEOUT = 100; size_t respond_to_client(int client_fd) { - char buffer[BUFSIZE]; - ssize_t total_bytes_read = 0, bytes_read = 0; - while ((bytes_read = recv(client_fd, buffer, BUFSIZE, 0)) > 0) { - total_bytes_read += bytes_read; - // Echo back the data received from the client - send(client_fd, buffer, bytes_read, 0); - } - return total_bytes_read; + char buffer[BUFSIZE]; + ssize_t total_bytes_read = 0, bytes_read = 0; + while ((bytes_read = recv(client_fd, buffer, BUFSIZE, 0)) > 0) { + total_bytes_read += bytes_read; + // Echo back the data received from the client + send(client_fd, buffer, bytes_read, 0); + } + return total_bytes_read; } void run_tcp_server() { - // Prepare server socket - int server_port = 4001; - // Use blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + // Prepare server socket + int server_port = 4001; + // Use blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); - // Listen on socket - socklen_t client_len = sizeof(struct sockaddr_in); - int client_socket_fd; - struct sockaddr_in client_address; - int32_t bytes_read = 0, total_bytes_read = 0; - TEST(listen(server_socket_fd, 1) != -1); + // Listen on socket + socklen_t client_len = sizeof(struct sockaddr_in); + int client_socket_fd; + struct sockaddr_in client_address; + int32_t bytes_read = 0, total_bytes_read = 0; + TEST(listen(server_socket_fd, 1) != -1); - // Server accepts connection - struct pollfd client_fds[EXPECTED_CONNECTIONS]; + // Server accepts connection + struct pollfd client_fds[EXPECTED_CONNECTIONS]; - // Wait until a fixed number of clients connect - for (size_t i = 0; i < EXPECTED_CONNECTIONS; i++) { - client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_address, &client_len); - TEST(client_socket_fd != -1); - client_fds[i].fd = client_socket_fd; - client_fds[i].events &= POLLIN; - } + // Wait until a fixed number of clients connect + for (size_t i = 0; i < EXPECTED_CONNECTIONS; i++) { + client_socket_fd = accept(server_socket_fd, + (struct sockaddr *)&client_address, &client_len); + TEST(client_socket_fd != -1); + client_fds[i].fd = client_socket_fd; + client_fds[i].events &= POLLIN; + } - // Poll on the array of client file descriptors and respond to - // any that are ready - size_t connections = 0; - while (poll(client_fds, EXPECTED_CONNECTIONS, TIMEOUT) != 0) { - for (int i = 0; i < EXPECTED_CONNECTIONS; i++) { - if (client_fds[i].revents | POLLIN) { - total_bytes_read += respond_to_client(client_fds[i].fd); - // If fd is negative, revents will be set to 0 on the next call - client_fds[i].fd = ~client_fds[i].fd; - } - } + // Poll on the array of client file descriptors and respond to + // any that are ready + size_t connections = 0; + while (poll(client_fds, EXPECTED_CONNECTIONS, TIMEOUT) != 0) { + for (int i = 0; i < EXPECTED_CONNECTIONS; i++) { + if (client_fds[i].revents | POLLIN) { + total_bytes_read += respond_to_client(client_fds[i].fd); + // If fd is negative, revents will be set to 0 on the next call + client_fds[i].fd = ~client_fds[i].fd; + } } + } - TEST(total_bytes_read > 0); + TEST(total_bytes_read > 0); - for (size_t i = 0; i < EXPECTED_CONNECTIONS; i++) { - // fd was set to the complement of itself, so - // it needs to be complemented again - close(~client_fds[i].fd); - } - close(server_socket_fd); + for (size_t i = 0; i < EXPECTED_CONNECTIONS; i++) { + // fd was set to the complement of itself, so + // it needs to be complemented again + close(~client_fds[i].fd); + } + close(server_socket_fd); } -int main() -{ - run_tcp_server(); +int main() { + run_tcp_server(); - return t_status; + return t_status; } diff --git a/test/src/sockets-nonblocking-multiple.c b/test/src/sockets-nonblocking-multiple.c index 1456c1fea..4fac1e405 100644 --- a/test/src/sockets-nonblocking-multiple.c +++ b/test/src/sockets-nonblocking-multiple.c @@ -1,286 +1,325 @@ +#include "test.h" +#include #include #include -#include +#include +#include +#include #include +#include #include #include -#include -#include #include -#include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) // #define _DEBUG 1 #ifdef _DEBUG -#define DEBUG_PRINT(...) fprintf( stderr, __VA_ARGS__ ); fflush(stdout) +#define DEBUG_PRINT(...) \ + fprintf(stderr, __VA_ARGS__); \ + fflush(stdout) #else -#define DEBUG_PRINT(...) do{ } while ( 0 ) +#define DEBUG_PRINT(...) \ + do { \ + } while (0) #endif - #define BUFSIZE 256 size_t MAX_CONNECTIONS = 10; struct response { - int recipient_fd; - char message[BUFSIZE]; + int recipient_fd; + char message[BUFSIZE]; }; struct request { - bool sent; - char message[BUFSIZE]; + bool sent; + char message[BUFSIZE]; }; // We are done if client_incoming == client_outgoing -bool done(struct request out[MAX_CONNECTIONS], char in[MAX_CONNECTIONS][BUFSIZE]) { - DEBUG_PRINT("Checking if we're done\n"); - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - if (out[i].message[0] == 0) { - return false; - } - if (strcmp(out[i].message, in[i]) != 0) { - DEBUG_PRINT("%zu does not match: (%s) (%s)\n", i, out[i].message, in[i]); - return false; - } - DEBUG_PRINT("%zu matches\n", i); +bool done(struct request out[MAX_CONNECTIONS], + char in[MAX_CONNECTIONS][BUFSIZE]) { + DEBUG_PRINT("Checking if we're done\n"); + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + if (out[i].message[0] == 0) { + return false; } - for (size_t i = 0; i < MAX_CONNECTIONS; i++) - DEBUG_PRINT("out = %s in = %s\n", out[i].message, in[i]); - return true; + if (strcmp(out[i].message, in[i]) != 0) { + DEBUG_PRINT("%zu does not match: (%s) (%s)\n", i, out[i].message, in[i]); + return false; + } + DEBUG_PRINT("%zu matches\n", i); + } + for (size_t i = 0; i < MAX_CONNECTIONS; i++) + DEBUG_PRINT("out = %s in = %s\n", out[i].message, in[i]); + return true; } // See sockets-server.c -- must be running already as a separate executable void test_tcp_client() { - // Prepare server socket - int server_port = 4001; - // Use non-blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); - - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); + // Prepare server socket + int server_port = 4001; + // Use non-blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); - // Listen on socket - char buffer[BUFSIZE]; - socklen_t client_len = sizeof(struct sockaddr_in); - int client_socket_fd = -1; - struct sockaddr_in client_address; - int32_t bytes_read = 0, total_bytes_read = 0; - TEST(listen(server_socket_fd, 1) != -1); - - // Prepare client sockets - int client_sockets[MAX_CONNECTIONS]; - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - // Use non-blocking sockets - client_sockets[i] = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); - TEST(client_sockets[i] != -1); - } + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); + // Listen on socket + char buffer[BUFSIZE]; + socklen_t client_len = sizeof(struct sockaddr_in); + int client_socket_fd = -1; + struct sockaddr_in client_address; + int32_t bytes_read = 0, total_bytes_read = 0; + TEST(listen(server_socket_fd, 1) != -1); - // Connect from client - struct request client_outgoing[MAX_CONNECTIONS]; - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - int32_t number = 0; - getentropy(&number, sizeof(int32_t)); - sprintf(client_outgoing[i].message, "%d", number); - client_outgoing[i].sent = false; - } - char client_incoming[MAX_CONNECTIONS][BUFSIZE]; - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - client_incoming[i][0] = 0; - } + // Prepare client sockets + int client_sockets[MAX_CONNECTIONS]; + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + // Use non-blocking sockets + client_sockets[i] = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + TEST(client_sockets[i] != -1); + } - int server_sockets[MAX_CONNECTIONS]; - int next_server_socket = 0; - struct pollfd poll_fd_server[MAX_CONNECTIONS + 1]; - struct pollfd poll_fd_client[MAX_CONNECTIONS]; - char server_incoming[MAX_CONNECTIONS + 1][BUFSIZE]; - struct response server_outgoing[MAX_CONNECTIONS + 1]; - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - server_outgoing[i].message[0] = 0; - } - poll_fd_server[0].fd = server_socket_fd; - poll_fd_server[0].events = POLLRDNORM; - poll_fd_server[0].revents = 0; - int next_client = 0; - bool failure = false; + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); - while (!done(client_outgoing, client_incoming) && (next_client < MAX_CONNECTIONS * 2)) { + // Connect from client + struct request client_outgoing[MAX_CONNECTIONS]; + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + int32_t number = 0; + getentropy(&number, sizeof(int32_t)); + sprintf(client_outgoing[i].message, "%d", number); + client_outgoing[i].sent = false; + } + char client_incoming[MAX_CONNECTIONS][BUFSIZE]; + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + client_incoming[i][0] = 0; + } - DEBUG_PRINT("============== next_client = %d ================\n", next_client); + int server_sockets[MAX_CONNECTIONS]; + int next_server_socket = 0; + struct pollfd poll_fd_server[MAX_CONNECTIONS + 1]; + struct pollfd poll_fd_client[MAX_CONNECTIONS]; + char server_incoming[MAX_CONNECTIONS + 1][BUFSIZE]; + struct response server_outgoing[MAX_CONNECTIONS + 1]; + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + server_outgoing[i].message[0] = 0; + } + poll_fd_server[0].fd = server_socket_fd; + poll_fd_server[0].events = POLLRDNORM; + poll_fd_server[0].revents = 0; + int next_client = 0; + bool failure = false; - // One client tries to connect - if (next_client < MAX_CONNECTIONS) { - int connect_result = connect(client_sockets[next_client], (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in)); - if (connect_result == 0 || errno == EINPROGRESS || errno == EISCONN) { - int32_t error = -1; - socklen_t len = -1; + while (!done(client_outgoing, client_incoming) && + (next_client < MAX_CONNECTIONS * 2)) { - struct pollfd poll_fd = { .fd = client_sockets[next_client], .events = POLLWRNORM, .revents = 0 }; - int getsockopt_result = getsockopt(client_sockets[next_client], SOL_SOCKET, SO_ERROR, &error, &len); - poll(&poll_fd, 1, 100); - // Check if socket has become writable - TEST(getsockopt(client_sockets[next_client], SOL_SOCKET, SO_ERROR, &error, &len) == 0); - if (error == 0) { - next_client++; - poll_fd_server[next_client].events = POLLRDNORM; - poll_fd_server[next_client].revents = 0; - poll_fd_client[next_client - 1].fd = client_sockets[next_client - 1]; - poll_fd_client[next_client - 1].events = POLLWRNORM; - poll_fd_server[next_client - 1].revents = 0; - DEBUG_PRINT("Client [#%d] = %d connected\n", next_client - 1, client_sockets[next_client - 1]); - } - } else { - failure = true; - DEBUG_PRINT("FAILURE: client %d failed to connect: %s\n", client_sockets[next_client], strerror(errno)); - break; - } - errno = 0; - } else - DEBUG_PRINT("No longer accepting connections\n"); + DEBUG_PRINT("============== next_client = %d ================\n", + next_client); - // Server polls for new connections and activity on existing connections, simultaneously - poll(poll_fd_server, next_server_socket + 1, 100); - int to_poll = next_server_socket + 1; - bool recv_failed = false; - DEBUG_PRINT("Server looping through poll events errno = %s\n", strerror(errno)); - for (size_t i = 0; i < to_poll; i++) { - if (i == 0) { - int accept_result = accept4(server_socket_fd, (struct sockaddr*)&client_address, &client_len, SOCK_NONBLOCK); - if (accept_result != -1) { - server_sockets[next_server_socket] = accept_result; - DEBUG_PRINT("Server accepted new connection: %d, storing in %d\n", server_sockets[next_server_socket], next_server_socket); - poll_fd_server[next_client].fd = server_sockets[next_server_socket]; - next_server_socket++; - } - errno = 0; - } - else { - DEBUG_PRINT("poll_fd_server[%zu].revents = %d (fd = %d) errno = %d\n", i, poll_fd_server[i].revents, poll_fd_server[i].fd, errno); - if (poll_fd_server[i].revents & POLLRDNORM) { - int recv_result = recv(poll_fd_server[i].fd, &server_incoming[i], BUFSIZE, 0); - if (recv_result == -1 && (errno == EAGAIN)) { - // This shouldn't happen -- poll() reported that there was data - DEBUG_PRINT("Shouldn't happen -- poll() said there was data but recv() returned EAGAIN\n"); - errno = 0; - } else if (recv_result == -1) { - recv_failed = true; - } - else { - server_outgoing[i].recipient_fd = poll_fd_server[i].fd; - memcpy(server_outgoing[i].message, server_incoming[i], recv_result); - server_outgoing[i].message[recv_result] = 0; - DEBUG_PRINT("Received message: %s from %d (%d bytes)\n", server_outgoing[i].message, poll_fd_server[i].fd, recv_result); - } - } - } - } + // One client tries to connect + if (next_client < MAX_CONNECTIONS) { + int connect_result = + connect(client_sockets[next_client], (struct sockaddr *)&sockaddr_in, + sizeof(sockaddr_in)); + if (connect_result == 0 || errno == EINPROGRESS || errno == EISCONN) { + int32_t error = -1; + socklen_t len = -1; - if (recv_failed) { - DEBUG_PRINT("FAILURE: server reading from client failed\n"); - failure = true; - break; + struct pollfd poll_fd = {.fd = client_sockets[next_client], + .events = POLLWRNORM, + .revents = 0}; + int getsockopt_result = getsockopt(client_sockets[next_client], + SOL_SOCKET, SO_ERROR, &error, &len); + poll(&poll_fd, 1, 100); + // Check if socket has become writable + TEST(getsockopt(client_sockets[next_client], SOL_SOCKET, SO_ERROR, + &error, &len) == 0); + if (error == 0) { + next_client++; + poll_fd_server[next_client].events = POLLRDNORM; + poll_fd_server[next_client].revents = 0; + poll_fd_client[next_client - 1].fd = client_sockets[next_client - 1]; + poll_fd_client[next_client - 1].events = POLLWRNORM; + poll_fd_server[next_client - 1].revents = 0; + DEBUG_PRINT("Client [#%d] = %d connected\n", next_client - 1, + client_sockets[next_client - 1]); } + } else { + failure = true; + DEBUG_PRINT("FAILURE: client %d failed to connect: %s\n", + client_sockets[next_client], strerror(errno)); + break; + } + errno = 0; + } else + DEBUG_PRINT("No longer accepting connections\n"); - // All connected clients try to send - bool send_failed = false; - for (int32_t i = 0; i < next_client; i++) { - DEBUG_PRINT("client_outgoing[%d] %s\n", i, client_outgoing[i].sent ? "sent" : "not sent"); - if (!client_outgoing[i].sent) { - client_outgoing[i].sent = true; - int send_result = send(client_sockets[i], client_outgoing[i].message, strlen(client_outgoing[i].message), 0); - DEBUG_PRINT("Client %d sent %s with result %d and error = %s\n", client_sockets[i], client_outgoing[i].message, send_result, strerror(errno)); - if (errno == EAGAIN) { - struct pollfd poll_fd = { .fd = client_sockets[i], .events = POLLWRNORM, .revents = 0 }; - poll(&poll_fd, 1, 100); - // Check if socket has become writable - int32_t error = -1; - socklen_t len = -1; - TEST(getsockopt(client_sockets[i], SOL_SOCKET, SO_ERROR, &error, &len) == 0); - if (error != 0) { - send_failed = true; - break; - } - errno = 0; - } else if (send_result == -1) { - send_failed = true; - break; - } - } + // Server polls for new connections and activity on existing connections, + // simultaneously + poll(poll_fd_server, next_server_socket + 1, 100); + int to_poll = next_server_socket + 1; + bool recv_failed = false; + DEBUG_PRINT("Server looping through poll events errno = %s\n", + strerror(errno)); + for (size_t i = 0; i < to_poll; i++) { + if (i == 0) { + int accept_result = + accept4(server_socket_fd, (struct sockaddr *)&client_address, + &client_len, SOCK_NONBLOCK); + if (accept_result != -1) { + server_sockets[next_server_socket] = accept_result; + DEBUG_PRINT("Server accepted new connection: %d, storing in %d\n", + server_sockets[next_server_socket], next_server_socket); + poll_fd_server[next_client].fd = server_sockets[next_server_socket]; + next_server_socket++; } - - if (send_failed) { - DEBUG_PRINT("FAILURE: client sending to server failed\n"); - failure = true; - break; + errno = 0; + } else { + DEBUG_PRINT("poll_fd_server[%zu].revents = %d (fd = %d) errno = %d\n", + i, poll_fd_server[i].revents, poll_fd_server[i].fd, errno); + if (poll_fd_server[i].revents & POLLRDNORM) { + int recv_result = + recv(poll_fd_server[i].fd, &server_incoming[i], BUFSIZE, 0); + if (recv_result == -1 && (errno == EAGAIN)) { + // This shouldn't happen -- poll() reported that there was data + DEBUG_PRINT("Shouldn't happen -- poll() said there was data but " + "recv() returned EAGAIN\n"); + errno = 0; + } else if (recv_result == -1) { + recv_failed = true; + } else { + server_outgoing[i].recipient_fd = poll_fd_server[i].fd; + memcpy(server_outgoing[i].message, server_incoming[i], recv_result); + server_outgoing[i].message[recv_result] = 0; + DEBUG_PRINT("Received message: %s from %d (%d bytes)\n", + server_outgoing[i].message, poll_fd_server[i].fd, + recv_result); + } } + } + } - // All connected clients try to receive - if (next_client > 0) { - for (int32_t i = 0; i < next_client; i++) - poll_fd_client[i].events = POLLRDNORM; - poll(poll_fd_client, next_client, 100); - } - DEBUG_PRINT("Looping through poll events\n"); - for (int32_t i = 0; i < next_client; i++) { - DEBUG_PRINT("poll_fd_client[%d].revents = %d\n", i, poll_fd_client[i].revents); - if (poll_fd_client[i].revents & POLLRDNORM) { - int bytes_received = recv(poll_fd_client[i].fd, client_incoming[i], BUFSIZE, 0); - DEBUG_PRINT("Client %d received message %s, expected %s [received %d bytes, length of incoming = %lu]\n", poll_fd_client[i].fd, client_incoming[i], client_outgoing[i].message, bytes_received, strlen(client_incoming[i])); - TEST(strcmp(client_outgoing[i].message, client_incoming[i]) == 0); - } - } - DEBUG_PRINT("Looped through poll events\n"); + if (recv_failed) { + DEBUG_PRINT("FAILURE: server reading from client failed\n"); + failure = true; + break; + } - // Server replies to any pending messages - for (size_t i = 0; i < MAX_CONNECTIONS + 1; i++) { - if (server_outgoing[i].message[0]) { - int send_result = send(server_outgoing[i].recipient_fd, server_outgoing[i].message, strlen(server_outgoing[i].message) + 1, 0); - DEBUG_PRINT("Server sent %s to %d (sent: %d bytes)\n", server_outgoing[i].message, poll_fd_server[i].fd, send_result); - server_outgoing[i].message[0] = 0; - } + // All connected clients try to send + bool send_failed = false; + for (int32_t i = 0; i < next_client; i++) { + DEBUG_PRINT("client_outgoing[%d] %s\n", i, + client_outgoing[i].sent ? "sent" : "not sent"); + if (!client_outgoing[i].sent) { + client_outgoing[i].sent = true; + int send_result = send(client_sockets[i], client_outgoing[i].message, + strlen(client_outgoing[i].message), 0); + DEBUG_PRINT("Client %d sent %s with result %d and error = %s\n", + client_sockets[i], client_outgoing[i].message, send_result, + strerror(errno)); + if (errno == EAGAIN) { + struct pollfd poll_fd = { + .fd = client_sockets[i], .events = POLLWRNORM, .revents = 0}; + poll(&poll_fd, 1, 100); + // Check if socket has become writable + int32_t error = -1; + socklen_t len = -1; + TEST(getsockopt(client_sockets[i], SOL_SOCKET, SO_ERROR, &error, + &len) == 0); + if (error != 0) { + send_failed = true; + break; + } + errno = 0; + } else if (send_result == -1) { + send_failed = true; + break; } + } } - TEST(failure==false); - TEST(next_client==MAX_CONNECTIONS); + if (send_failed) { + DEBUG_PRINT("FAILURE: client sending to server failed\n"); + failure = true; + break; + } - // Clients shut themselves down - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - TEST(client_sockets[i] != -1); - close(client_sockets[i]); + // All connected clients try to receive + if (next_client > 0) { + for (int32_t i = 0; i < next_client; i++) + poll_fd_client[i].events = POLLRDNORM; + poll(poll_fd_client, next_client, 100); } + DEBUG_PRINT("Looping through poll events\n"); + for (int32_t i = 0; i < next_client; i++) { + DEBUG_PRINT("poll_fd_client[%d].revents = %d\n", i, + poll_fd_client[i].revents); + if (poll_fd_client[i].revents & POLLRDNORM) { + int bytes_received = + recv(poll_fd_client[i].fd, client_incoming[i], BUFSIZE, 0); + DEBUG_PRINT("Client %d received message %s, expected %s [received %d " + "bytes, length of incoming = %lu]\n", + poll_fd_client[i].fd, client_incoming[i], + client_outgoing[i].message, bytes_received, + strlen(client_incoming[i])); + TEST(strcmp(client_outgoing[i].message, client_incoming[i]) == 0); + } + } + DEBUG_PRINT("Looped through poll events\n"); - // Server shuts down all connections - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - TEST(server_sockets[i] != -1); - close(server_sockets[i]); + // Server replies to any pending messages + for (size_t i = 0; i < MAX_CONNECTIONS + 1; i++) { + if (server_outgoing[i].message[0]) { + int send_result = + send(server_outgoing[i].recipient_fd, server_outgoing[i].message, + strlen(server_outgoing[i].message) + 1, 0); + DEBUG_PRINT("Server sent %s to %d (sent: %d bytes)\n", + server_outgoing[i].message, poll_fd_server[i].fd, + send_result); + server_outgoing[i].message[0] = 0; + } } + } + + TEST(failure == false); + TEST(next_client == MAX_CONNECTIONS); + + // Clients shut themselves down + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + TEST(client_sockets[i] != -1); + close(client_sockets[i]); + } + + // Server shuts down all connections + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + TEST(server_sockets[i] != -1); + close(server_sockets[i]); + } - // Server shuts down - close(server_socket_fd); + // Server shuts down + close(server_socket_fd); } -int main(void) -{ - test_tcp_client(); +int main(void) { + test_tcp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-nonblocking-udp-multiple.c b/test/src/sockets-nonblocking-udp-multiple.c index 3f2dfeb86..22cac6c47 100644 --- a/test/src/sockets-nonblocking-udp-multiple.c +++ b/test/src/sockets-nonblocking-udp-multiple.c @@ -1,217 +1,247 @@ +#include "test.h" +#include #include #include +#include +#include +#include +#include #include #include -#include #include -#include -#include #include -#include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) // #define _DEBUG 1 #ifdef _DEBUG -#define DEBUG_PRINT(...) fprintf( stderr, __VA_ARGS__ ); fflush(stdout) +#define DEBUG_PRINT(...) \ + fprintf(stderr, __VA_ARGS__); \ + fflush(stdout) #else -#define DEBUG_PRINT(...) do{ } while ( 0 ) +#define DEBUG_PRINT(...) \ + do { \ + } while (0) #endif #define BUFSIZE 256 int MAX_CONNECTIONS = 10; struct response { - bool responded; - char message[BUFSIZE]; - int32_t client_index; + bool responded; + char message[BUFSIZE]; + int32_t client_index; }; struct request { - bool sent; - char message[BUFSIZE]; + bool sent; + char message[BUFSIZE]; }; // We are done if client_incoming == client_outgoing -bool done(struct request out[MAX_CONNECTIONS], char in[MAX_CONNECTIONS][BUFSIZE]) { - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - if (out[i].message[0] == 0) { - return false; - } - if (strcmp(out[i].message, in[i]) != 0) { - DEBUG_PRINT("sent[%zu] = %s != received[%zu] = %s\n", i, out[i].message, i, in[i]); - return false; - } - DEBUG_PRINT("i = %zu %s matches %s\n", i, out[i].message, in[i]); +bool done(struct request out[MAX_CONNECTIONS], + char in[MAX_CONNECTIONS][BUFSIZE]) { + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + if (out[i].message[0] == 0) { + return false; + } + if (strcmp(out[i].message, in[i]) != 0) { + DEBUG_PRINT("sent[%zu] = %s != received[%zu] = %s\n", i, out[i].message, + i, in[i]); + return false; } - return true; + DEBUG_PRINT("i = %zu %s matches %s\n", i, out[i].message, in[i]); + } + return true; } void test_udp_client() { - // Prepare server socket - int server_port = 4001; - // Use non-blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); - - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); - - // Prepare client sockets - // Use non-blocking sockets - int client_sockets[MAX_CONNECTIONS]; - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - client_sockets[i] = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); - TEST(client_sockets[i] != -1); + // Prepare server socket + int server_port = 4001; + // Use non-blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); + + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); + + // Prepare client sockets + // Use non-blocking sockets + int client_sockets[MAX_CONNECTIONS]; + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + client_sockets[i] = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); + TEST(client_sockets[i] != -1); + } + + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); + + // Prepare requests from clients + struct request client_outgoing[MAX_CONNECTIONS]; + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + int32_t number = 0; + getentropy(&number, sizeof(int32_t)); + sprintf(client_outgoing[i].message, "%d", number); + client_outgoing[i].sent = false; + } + char client_incoming[MAX_CONNECTIONS][BUFSIZE]; + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + client_incoming[i][0] = 0; + } + struct response server_incoming[MAX_CONNECTIONS]; + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + server_incoming[i].responded = false; + server_incoming[i].message[0] = 0; + } + struct pollfd client_pollfds[MAX_CONNECTIONS]; + for (size_t i = 0; i < MAX_CONNECTIONS; i++) { + client_pollfds[i].fd = client_sockets[i]; + client_pollfds[i].events = POLLRDNORM; + client_pollfds[i].revents = 0; + } + + struct sockaddr_in addresses_of_clients[MAX_CONNECTIONS]; + socklen_t address_len = sizeof(sockaddr_in); + + struct pollfd server_pollfd = { + .fd = server_socket_fd, .events = POLLRDNORM, .revents = 0}; + struct pollfd server_client_pollfds[MAX_CONNECTIONS]; + size_t next_client = 0; + size_t server_client_index = 0; + int32_t tries = 0; + while (!done(client_outgoing, client_incoming) && + (tries < (MAX_CONNECTIONS * 2))) { + DEBUG_PRINT("server polling for new messages\n"); + + // Server polls for new messages + server_pollfd.events = POLLRDNORM; + poll(&server_pollfd, 1, 100); + if ((server_pollfd.revents & POLLRDNORM) != 0) { + int bytes_received = recvfrom( + server_socket_fd, server_incoming[server_client_index].message, + BUFSIZE, 0, + (struct sockaddr *)&(addresses_of_clients[server_client_index]), + &address_len); + if (bytes_received > 0) { + server_incoming[server_client_index].client_index = server_client_index; + server_client_index++; + } else + DEBUG_PRINT("Shouldn't happen: poll(server_pollfd) said there is data " + "but recvfrom() failed to return it\n"); } - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); - - // Prepare requests from clients - struct request client_outgoing[MAX_CONNECTIONS]; - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - int32_t number = 0; - getentropy(&number, sizeof(int32_t)); - sprintf(client_outgoing[i].message, "%d", number); - client_outgoing[i].sent = false; + DEBUG_PRINT("next client sending\n"); + // Next client sends + if (next_client < MAX_CONNECTIONS) { + struct pollfd client_pollfd = {.fd = client_sockets[next_client], + .events = POLLWRNORM, + .revents = 0}; + poll(&client_pollfd, 1, 100); + if ((client_pollfd.events & POLLWRNORM) != 0) { + int32_t bytes_sent = sendto( + client_sockets[next_client], client_outgoing[next_client].message, + strlen(client_outgoing[next_client].message) + 1, 0, + (struct sockaddr *)&sockaddr_in, address_len); + if (bytes_sent == -1) { + DEBUG_PRINT("client %zu failed to send, error: %s\n", next_client, + strerror(errno)); + TEST(errno == EWOULDBLOCK); + // Will retry on next iteration of loop + } else { + DEBUG_PRINT("client %zu sent %d bytes\n", next_client, bytes_sent); + client_outgoing[next_client].sent = true; + if (next_client < MAX_CONNECTIONS) + next_client++; + } + } } - char client_incoming[MAX_CONNECTIONS][BUFSIZE]; - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - client_incoming[i][0] = 0; + + DEBUG_PRINT("server echoing\n"); + // Echo messages back to clients + server_pollfd.events = POLLWRNORM; + poll(&server_pollfd, 1, 100); + for (size_t i = 0; i < server_client_index; i++) { + if (server_incoming[i].message[0] != 0 && !server_incoming[i].responded) { + ssize_t bytes_sent = + sendto(server_socket_fd, server_incoming[i].message, BUFSIZE, 0, + (struct sockaddr *)&addresses_of_clients[i], address_len); + if (bytes_sent == -1) { + int the_error = errno; + TEST(the_error == EWOULDBLOCK); + // Will retry on next iteration of loop + } else { + DEBUG_PRINT("server echoed message %s back to client %zu\n", + server_incoming[i].message, i); + server_incoming[i].responded = true; + } + break; + } } - struct response server_incoming[MAX_CONNECTIONS]; + + DEBUG_PRINT("clients receiving\n"); + // Clients receive messages + poll(client_pollfds, MAX_CONNECTIONS, 100); + DEBUG_PRINT("======= client_pollfds: =========\n"); for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - server_incoming[i].responded = false; - server_incoming[i].message[0] = 0; + DEBUG_PRINT("{ .fd = %d .events = %d .revents = %d }\n", + client_pollfds[i].fd, client_pollfds[i].events, + client_pollfds[i].revents); } - struct pollfd client_pollfds[MAX_CONNECTIONS]; + DEBUG_PRINT("=================================\n"); for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - client_pollfds[i].fd = client_sockets[i]; - client_pollfds[i].events = POLLRDNORM; - client_pollfds[i].revents = 0; - } - - struct sockaddr_in addresses_of_clients[MAX_CONNECTIONS]; - socklen_t address_len = sizeof(sockaddr_in); - - struct pollfd server_pollfd = { .fd = server_socket_fd, .events = POLLRDNORM, .revents = 0 }; - struct pollfd server_client_pollfds[MAX_CONNECTIONS]; - size_t next_client = 0; - size_t server_client_index = 0; - int32_t tries = 0; - while (!done(client_outgoing, client_incoming) && (tries < (MAX_CONNECTIONS * 2))) { - DEBUG_PRINT("server polling for new messages\n"); - - // Server polls for new messages - server_pollfd.events = POLLRDNORM; - poll(&server_pollfd, 1, 100); - if ((server_pollfd.revents & POLLRDNORM) != 0) { - int bytes_received = recvfrom(server_socket_fd, server_incoming[server_client_index].message, - BUFSIZE, 0, (struct sockaddr*)&(addresses_of_clients[server_client_index]), &address_len); - if (bytes_received > 0) { - server_incoming[server_client_index].client_index = server_client_index; - server_client_index++; - } else - DEBUG_PRINT("Shouldn't happen: poll(server_pollfd) said there is data but recvfrom() failed to return it\n"); - } - - DEBUG_PRINT("next client sending\n"); - // Next client sends - if (next_client < MAX_CONNECTIONS) { - struct pollfd client_pollfd = { .fd = client_sockets[next_client], .events = POLLWRNORM, .revents = 0 }; - poll(&client_pollfd, 1, 100); - if ((client_pollfd.events & POLLWRNORM) != 0) { - int32_t bytes_sent = sendto(client_sockets[next_client], client_outgoing[next_client].message, - strlen(client_outgoing[next_client].message) + 1, 0, (struct sockaddr*)&sockaddr_in, address_len); - if (bytes_sent == -1) { - DEBUG_PRINT("client %zu failed to send, error: %s\n", next_client, strerror(errno)); - TEST(errno==EWOULDBLOCK); - // Will retry on next iteration of loop - } else { - DEBUG_PRINT("client %zu sent %d bytes\n", next_client, bytes_sent); - client_outgoing[next_client].sent = true; - if (next_client < MAX_CONNECTIONS) - next_client++; - } - } - } - - DEBUG_PRINT("server echoing\n"); - // Echo messages back to clients - server_pollfd.events = POLLWRNORM; - poll(&server_pollfd, 1, 100); - for (size_t i = 0; i < server_client_index; i++) { - if (server_incoming[i].message[0] != 0 && !server_incoming[i].responded) { - ssize_t bytes_sent = sendto(server_socket_fd, server_incoming[i].message, BUFSIZE, 0, (struct sockaddr*)&addresses_of_clients[i], address_len); - if (bytes_sent == -1) { - int the_error = errno; - TEST(the_error==EWOULDBLOCK); - // Will retry on next iteration of loop - } else { - DEBUG_PRINT("server echoed message %s back to client %zu\n", server_incoming[i].message, i); - server_incoming[i].responded = true; - } - break; - } - } - - DEBUG_PRINT("clients receiving\n"); - // Clients receive messages - poll(client_pollfds, MAX_CONNECTIONS, 100); - DEBUG_PRINT("======= client_pollfds: =========\n"); - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - DEBUG_PRINT("{ .fd = %d .events = %d .revents = %d }\n", client_pollfds[i].fd, client_pollfds[i].events, client_pollfds[i].revents); - } - DEBUG_PRINT("=================================\n"); - for (size_t i = 0; i < MAX_CONNECTIONS; i++) { - // Note: poll() will return revents == events for an unbound UDP socket; - // so that's why we check if we already sent on this socket, and do - // nothing if we haven't yet - if ((client_pollfds[i].revents & POLLRDNORM) != 0) { - DEBUG_PRINT("i = %zu, already received (%s), already sent? %s\n", i, client_incoming[i], client_outgoing[i].sent ? "yes" : "no"); - if (client_incoming[i][0] == 0 && client_outgoing[i].sent) { - int32_t bytes_received = recvfrom(client_pollfds[i].fd, &client_incoming[i], BUFSIZE, 0, (struct sockaddr*)&server_address, &address_len); - if (bytes_received != -1) { - DEBUG_PRINT("client %zu received message %s (%d bytes) from server\n", i, client_incoming[i], bytes_received); - } else { - DEBUG_PRINT("Shouldn't happen: poll() said there was data, but client %zu did not receive message from server: %s\n", i, strerror(errno)); - } - } - } + // Note: poll() will return revents == events for an unbound UDP socket; + // so that's why we check if we already sent on this socket, and do + // nothing if we haven't yet + if ((client_pollfds[i].revents & POLLRDNORM) != 0) { + DEBUG_PRINT("i = %zu, already received (%s), already sent? %s\n", i, + client_incoming[i], client_outgoing[i].sent ? "yes" : "no"); + if (client_incoming[i][0] == 0 && client_outgoing[i].sent) { + int32_t bytes_received = + recvfrom(client_pollfds[i].fd, &client_incoming[i], BUFSIZE, 0, + (struct sockaddr *)&server_address, &address_len); + if (bytes_received != -1) { + DEBUG_PRINT( + "client %zu received message %s (%d bytes) from server\n", i, + client_incoming[i], bytes_received); + } else { + DEBUG_PRINT("Shouldn't happen: poll() said there was data, but " + "client %zu did not receive message from server: %s\n", + i, strerror(errno)); + } } - tries++; + } } + tries++; + } - DEBUG_PRINT("========= exited loop ==========\n"); + DEBUG_PRINT("========= exited loop ==========\n"); - TEST(done(client_outgoing, client_incoming)); + TEST(done(client_outgoing, client_incoming)); - // Shut down clients - for (size_t i = 0; i < MAX_CONNECTIONS; i++) - close(client_sockets[i]); + // Shut down clients + for (size_t i = 0; i < MAX_CONNECTIONS; i++) + close(client_sockets[i]); - // Shut down server - close(server_socket_fd); + // Shut down server + close(server_socket_fd); } -int main(void) -{ - test_udp_client(); +int main(void) { + test_udp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-nonblocking-udp.c b/test/src/sockets-nonblocking-udp.c index 5a7d4490d..6d2deb1ea 100644 --- a/test/src/sockets-nonblocking-udp.c +++ b/test/src/sockets-nonblocking-udp.c @@ -1,116 +1,128 @@ +#include "test.h" +#include #include #include +#include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; void test_udp_client() { - // Prepare server socket - int server_port = 4001; - // Use non-blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); - - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); - - // Prepare client socket - // Use non-blocking sockets - int socket_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); - TEST(socket_fd != -1); - - // Prepare sockaddr_in for client - struct sockaddr_in sockaddr_in; - sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sockaddr_in.sin_family = AF_INET; - sockaddr_in.sin_port = htons(server_port); - - // TODO: Also test using sendto / recvfrom with socket not in a connected state - - // Connect from client - char message[] = "There's gonna be a party when the wolf comes home"; - int len = strlen(message); - char client_buffer[BUFSIZE]; - char server_buffer[BUFSIZE]; - int connect_result = connect(socket_fd, (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in)); - while (connect_result == -1) { - connect_result = connect(socket_fd, (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in)); - if (connect_result == -1) { - struct pollfd poll_fd = { .fd = socket_fd, .events = POLLWRNORM, .revents = 0 }; - poll(&poll_fd, 1, 100); - } - } - - // Write to socket - ssize_t bytes_sent = send(socket_fd, message, len + 1, 0); - - // Receive from client - struct sockaddr_in sockaddr_client; - socklen_t sockaddr_client_len = sizeof(sockaddr_in); - ssize_t bytes_received = recvfrom(server_socket_fd, server_buffer, BUFSIZE, 0, (struct sockaddr*)&sockaddr_client, &sockaddr_client_len); - if (bytes_received == -1) - if (errno != EWOULDBLOCK) - t_error("recvfrom failed (errno = %d)\n", errno); - - while (bytes_received == -1) { - struct pollfd poll_fd = { .fd = server_socket_fd, .events = POLLRDNORM, .revents = 0 }; - poll(&poll_fd, 1, 100); - bytes_received = recv(server_socket_fd, server_buffer, BUFSIZE, 0); + // Prepare server socket + int server_port = 4001; + // Use non-blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); + + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); + + // Prepare client socket + // Use non-blocking sockets + int socket_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); + TEST(socket_fd != -1); + + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); + + // TODO: Also test using sendto / recvfrom with socket not in a connected + // state + + // Connect from client + char message[] = "There's gonna be a party when the wolf comes home"; + int len = strlen(message); + char client_buffer[BUFSIZE]; + char server_buffer[BUFSIZE]; + int connect_result = + connect(socket_fd, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)); + while (connect_result == -1) { + connect_result = connect(socket_fd, (struct sockaddr *)&sockaddr_in, + sizeof(sockaddr_in)); + if (connect_result == -1) { + struct pollfd poll_fd = { + .fd = socket_fd, .events = POLLWRNORM, .revents = 0}; + poll(&poll_fd, 1, 100); } - - TEST(bytes_sent == len + 1); - TEST(bytes_received == len + 1); - - // Server echoes message back to client - bytes_sent = sendto(server_socket_fd, server_buffer, strlen(server_buffer) + 1, 0, (struct sockaddr*)&sockaddr_client, sockaddr_client_len); + } + + // Write to socket + ssize_t bytes_sent = send(socket_fd, message, len + 1, 0); + + // Receive from client + struct sockaddr_in sockaddr_client; + socklen_t sockaddr_client_len = sizeof(sockaddr_in); + ssize_t bytes_received = + recvfrom(server_socket_fd, server_buffer, BUFSIZE, 0, + (struct sockaddr *)&sockaddr_client, &sockaddr_client_len); + if (bytes_received == -1) + if (errno != EWOULDBLOCK) + t_error("recvfrom failed (errno = %d)\n", errno); + + while (bytes_received == -1) { + struct pollfd poll_fd = { + .fd = server_socket_fd, .events = POLLRDNORM, .revents = 0}; + poll(&poll_fd, 1, 100); + bytes_received = recv(server_socket_fd, server_buffer, BUFSIZE, 0); + } + + TEST(bytes_sent == len + 1); + TEST(bytes_received == len + 1); + + // Server echoes message back to client + bytes_sent = + sendto(server_socket_fd, server_buffer, strlen(server_buffer) + 1, 0, + (struct sockaddr *)&sockaddr_client, sockaddr_client_len); + bytes_received = recv(socket_fd, client_buffer, BUFSIZE, 0); + if (bytes_sent == -1) { + struct pollfd poll_fd = { + .fd = server_socket_fd, .events = POLLWRNORM, .revents = 0}; + poll(&poll_fd, 1, 100); + } + if (bytes_received == -1) { + struct pollfd poll_fd = { + .fd = socket_fd, .events = POLLRDNORM, .revents = 0}; + poll(&poll_fd, 1, 100); + // Retry bytes_received = recv(socket_fd, client_buffer, BUFSIZE, 0); - if (bytes_sent == -1) { - struct pollfd poll_fd = { .fd = server_socket_fd, .events = POLLWRNORM, .revents = 0 }; - poll(&poll_fd, 1, 100); - } - if (bytes_received == -1) { - struct pollfd poll_fd = { .fd = socket_fd, .events = POLLRDNORM, .revents = 0 }; - poll(&poll_fd, 1, 100); - // Retry - bytes_received = recv(socket_fd, client_buffer, BUFSIZE, 0); - } - // If bytes_received still < 1, consider it a timeout + } + // If bytes_received still < 1, consider it a timeout - TEST(bytes_sent == len + 1); - TEST(bytes_received == len + 1); + TEST(bytes_sent == len + 1); + TEST(bytes_received == len + 1); - // Message received should be the same as message sent - if (bytes_sent == bytes_received) - TEST(strcmp(message, client_buffer) == 0); + // Message received should be the same as message sent + if (bytes_sent == bytes_received) + TEST(strcmp(message, client_buffer) == 0); - // Shut down client - close(socket_fd); + // Shut down client + close(socket_fd); - // Shut down server - close(server_socket_fd); + // Shut down server + close(server_socket_fd); } -int main(void) -{ - test_udp_client(); +int main(void) { + test_udp_client(); - return t_status; + return t_status; } diff --git a/test/src/sockets-server-handle-hangups.c b/test/src/sockets-server-handle-hangups.c index 7c09ce558..35bcb6f19 100644 --- a/test/src/sockets-server-handle-hangups.c +++ b/test/src/sockets-server-handle-hangups.c @@ -1,72 +1,74 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; void run_tcp_server() { - // Prepare server socket - int server_port = 4001; - // Use blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + // Prepare server socket + int server_port = 4001; + // Use blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); - // Listen on socket - char buffer[BUFSIZE]; - socklen_t client_len = sizeof(struct sockaddr_in); - int client_socket_fd; - struct sockaddr_in client_address; - int32_t bytes_read = 0, total_bytes_read = 0; - TEST(listen(server_socket_fd, 1) != -1); + // Listen on socket + char buffer[BUFSIZE]; + socklen_t client_len = sizeof(struct sockaddr_in); + int client_socket_fd; + struct sockaddr_in client_address; + int32_t bytes_read = 0, total_bytes_read = 0; + TEST(listen(server_socket_fd, 1) != -1); - // Server accepts connection - client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_address, &client_len); - TEST(client_socket_fd != -1); + // Server accepts connection + client_socket_fd = + accept(server_socket_fd, (struct sockaddr *)&client_address, &client_len); + TEST(client_socket_fd != -1); -/* - Scenarios: - * Client hangs up after it connects - * Client hangs up while sending (set timeout to something very short?) - * Client hangs up after sending all data, but before receiving - * Client hangs up while receiving (set timeout to something very short) -*/ + /* + Scenarios: + * Client hangs up after it connects + * Client hangs up while sending (set timeout to something very short?) + * Client hangs up after sending all data, but before receiving + * Client hangs up while receiving (set timeout to something very short) + */ - // Server waits for input and echoes message back to client - // The server shuts down after the client closes the connection - while ((bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0)) > 0) { - total_bytes_read += bytes_read; - // Echo back the data received from the client - send(client_socket_fd, buffer, bytes_read, 0); - } + // Server waits for input and echoes message back to client + // The server shuts down after the client closes the connection + while ((bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0)) > 0) { + total_bytes_read += bytes_read; + // Echo back the data received from the client + send(client_socket_fd, buffer, bytes_read, 0); + } - close(client_socket_fd); - close(server_socket_fd); + close(client_socket_fd); + close(server_socket_fd); } -int main() -{ - run_tcp_server(); +int main() { + run_tcp_server(); - return t_status; + return t_status; } diff --git a/test/src/sockets-server-hangup-before-recv.c b/test/src/sockets-server-hangup-before-recv.c index 9dd94ff1d..b1402c0f5 100644 --- a/test/src/sockets-server-hangup-before-recv.c +++ b/test/src/sockets-server-hangup-before-recv.c @@ -1,63 +1,66 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; void run_tcp_server() { - // Prepare server socket - int server_port = 4001; - // Use blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); - - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); - - // Listen on socket - char buffer[BUFSIZE]; - socklen_t client_len = sizeof(struct sockaddr_in); - int client_socket_fd; - struct sockaddr_in client_address; - int32_t bytes_read = 0, total_bytes_read = 0; - TEST(listen(server_socket_fd, 1) != -1); - - // Server accepts connection - client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_address, &client_len); - TEST(client_socket_fd != -1); - - // Server waits for input, but closes the connection before sending anything back - while ((bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0)) > 0) { - total_bytes_read += bytes_read; - } - - TEST(total_bytes_read > 0); - - close(client_socket_fd); - close(server_socket_fd); + // Prepare server socket + int server_port = 4001; + // Use blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); + + // Listen on socket + char buffer[BUFSIZE]; + socklen_t client_len = sizeof(struct sockaddr_in); + int client_socket_fd; + struct sockaddr_in client_address; + int32_t bytes_read = 0, total_bytes_read = 0; + TEST(listen(server_socket_fd, 1) != -1); + + // Server accepts connection + client_socket_fd = + accept(server_socket_fd, (struct sockaddr *)&client_address, &client_len); + TEST(client_socket_fd != -1); + + // Server waits for input, but closes the connection before sending anything + // back + while ((bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0)) > 0) { + total_bytes_read += bytes_read; + } + + TEST(total_bytes_read > 0); + + close(client_socket_fd); + close(server_socket_fd); } -int main() -{ - run_tcp_server(); +int main() { + run_tcp_server(); - return t_status; + return t_status; } diff --git a/test/src/sockets-server-hangup-before-send.c b/test/src/sockets-server-hangup-before-send.c index 638089f95..721f6fd93 100644 --- a/test/src/sockets-server-hangup-before-send.c +++ b/test/src/sockets-server-hangup-before-send.c @@ -1,58 +1,60 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 16; void run_tcp_server() { - // Prepare server socket - int server_port = 4001; - // Use blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); - - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); - - // Listen on socket - char buffer[BUFSIZE]; - socklen_t client_len = sizeof(struct sockaddr_in); - int client_socket_fd; - struct sockaddr_in client_address; - int32_t bytes_read = 0, total_bytes_read = 0; - TEST(listen(server_socket_fd, 1) != -1); - - // Server accepts connection - client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_address, &client_len); - TEST(client_socket_fd != -1); - - // Server immediately hangs up - close(client_socket_fd); - - close(server_socket_fd); + // Prepare server socket + int server_port = 4001; + // Use blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); + + // Listen on socket + char buffer[BUFSIZE]; + socklen_t client_len = sizeof(struct sockaddr_in); + int client_socket_fd; + struct sockaddr_in client_address; + int32_t bytes_read = 0, total_bytes_read = 0; + TEST(listen(server_socket_fd, 1) != -1); + + // Server accepts connection + client_socket_fd = + accept(server_socket_fd, (struct sockaddr *)&client_address, &client_len); + TEST(client_socket_fd != -1); + + // Server immediately hangs up + close(client_socket_fd); + + close(server_socket_fd); } -int main() -{ - run_tcp_server(); +int main() { + run_tcp_server(); - return t_status; + return t_status; } diff --git a/test/src/sockets-server-hangup-during-recv.c b/test/src/sockets-server-hangup-during-recv.c index 0fee9b756..f223e52a8 100644 --- a/test/src/sockets-server-hangup-during-recv.c +++ b/test/src/sockets-server-hangup-during-recv.c @@ -1,62 +1,64 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 16; void run_tcp_server() { - // Prepare server socket - int server_port = 4001; - // Use blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); - - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); - - // Listen on socket - char buffer[BUFSIZE]; - socklen_t client_len = sizeof(struct sockaddr_in); - int client_socket_fd; - struct sockaddr_in client_address; - int32_t bytes_read = 0, total_bytes_read = 0; - TEST(listen(server_socket_fd, 1) != -1); - - // Server accepts connection - client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_address, &client_len); - TEST(client_socket_fd != -1); - - // Server waits for input, but hangs up before receiving entire message - bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0); - close(client_socket_fd); - - TEST(bytes_read > 0); - - close(client_socket_fd); - close(server_socket_fd); + // Prepare server socket + int server_port = 4001; + // Use blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); + + // Listen on socket + char buffer[BUFSIZE]; + socklen_t client_len = sizeof(struct sockaddr_in); + int client_socket_fd; + struct sockaddr_in client_address; + int32_t bytes_read = 0, total_bytes_read = 0; + TEST(listen(server_socket_fd, 1) != -1); + + // Server accepts connection + client_socket_fd = + accept(server_socket_fd, (struct sockaddr *)&client_address, &client_len); + TEST(client_socket_fd != -1); + + // Server waits for input, but hangs up before receiving entire message + bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0); + close(client_socket_fd); + + TEST(bytes_read > 0); + + close(client_socket_fd); + close(server_socket_fd); } -int main() -{ - run_tcp_server(); +int main() { + run_tcp_server(); - return t_status; + return t_status; } diff --git a/test/src/sockets-server-hangup-during-send.c b/test/src/sockets-server-hangup-during-send.c index 606f5742b..683498f17 100644 --- a/test/src/sockets-server-hangup-during-send.c +++ b/test/src/sockets-server-hangup-during-send.c @@ -1,60 +1,62 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 16; void run_tcp_server() { - // Prepare server socket - int server_port = 4001; - // Use blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); - - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); - - // Listen on socket - char buffer[BUFSIZE]; - socklen_t client_len = sizeof(struct sockaddr_in); - int client_socket_fd; - struct sockaddr_in client_address; - int32_t bytes_read = 0, total_bytes_read = 0; - TEST(listen(server_socket_fd, 1) != -1); - - // Server accepts connection - client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_address, &client_len); - TEST(client_socket_fd != -1); - - // Server partially receives data, then hangs up - bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0); - close(client_socket_fd); - TEST(bytes_read > 0); - - close(server_socket_fd); + // Prepare server socket + int server_port = 4001; + // Use blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); + + // Listen on socket + char buffer[BUFSIZE]; + socklen_t client_len = sizeof(struct sockaddr_in); + int client_socket_fd; + struct sockaddr_in client_address; + int32_t bytes_read = 0, total_bytes_read = 0; + TEST(listen(server_socket_fd, 1) != -1); + + // Server accepts connection + client_socket_fd = + accept(server_socket_fd, (struct sockaddr *)&client_address, &client_len); + TEST(client_socket_fd != -1); + + // Server partially receives data, then hangs up + bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0); + close(client_socket_fd); + TEST(bytes_read > 0); + + close(server_socket_fd); } -int main() -{ - run_tcp_server(); +int main() { + run_tcp_server(); - return t_status; + return t_status; } diff --git a/test/src/sockets-server-udp-blocking.c b/test/src/sockets-server-udp-blocking.c index 625b20528..16af04091 100644 --- a/test/src/sockets-server-udp-blocking.c +++ b/test/src/sockets-server-udp-blocking.c @@ -1,67 +1,71 @@ +#include "test.h" +#include #include #include +#include +#include +#include #include #include #include #include -#include -#include #include -#include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; void run_udp_server() { - // Prepare server socket - int server_port = 4001; - // Use blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_DGRAM, 0); + // Prepare server socket + int server_port = 4001; + // Use blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_DGRAM, 0); - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); - struct sockaddr_in client_address; - socklen_t address_len = sizeof(client_address); + struct sockaddr_in client_address; + socklen_t address_len = sizeof(client_address); - // Bind a TCP socket as well which the client will connect to as a - // synchronization mechanism to ensure the above UDP port is bound. - int tcp_socket_fd = socket(AF_INET, SOCK_STREAM, 0); - TEST(bind(tcp_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); - TEST(listen(tcp_socket_fd, 1) != -1); + // Bind a TCP socket as well which the client will connect to as a + // synchronization mechanism to ensure the above UDP port is bound. + int tcp_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + TEST(bind(tcp_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); + TEST(listen(tcp_socket_fd, 1) != -1); - // Server waits for input and echoes message back to client - // The server shuts down after the client closes the connection - int bytes_read = 0; - char buffer[BUFSIZE]; + // Server waits for input and echoes message back to client + // The server shuts down after the client closes the connection + int bytes_read = 0; + char buffer[BUFSIZE]; - while (bytes_read <= 0) { - bytes_read = recvfrom(server_socket_fd, buffer, BUFSIZE, 0, (struct sockaddr*)&client_address, &address_len); - if (bytes_read > 0) - sendto(server_socket_fd, buffer, bytes_read, 0, (struct sockaddr*)&client_address, address_len); - } + while (bytes_read <= 0) { + bytes_read = recvfrom(server_socket_fd, buffer, BUFSIZE, 0, + (struct sockaddr *)&client_address, &address_len); + if (bytes_read > 0) + sendto(server_socket_fd, buffer, bytes_read, 0, + (struct sockaddr *)&client_address, address_len); + } - TEST(bytes_read > 0); + TEST(bytes_read > 0); - close(server_socket_fd); - close(tcp_socket_fd); + close(server_socket_fd); + close(tcp_socket_fd); } -int main() -{ - run_udp_server(); +int main() { + run_udp_server(); - return t_status; + return t_status; } diff --git a/test/src/sockets-server.c b/test/src/sockets-server.c index 14c7a0d23..cc1a6f95f 100644 --- a/test/src/sockets-server.c +++ b/test/src/sockets-server.c @@ -1,66 +1,68 @@ +#include "test.h" +#include #include #include +#include +#include #include #include #include #include -#include -#include #include -#include -#include -#include "test.h" +#include -#define TEST(c) do { \ - errno = 0; \ - if (!(c)) \ - t_error("%s failed (errno = %d)\n", #c, errno); \ -} while(0) +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) int BUFSIZE = 256; void run_tcp_server() { - // Prepare server socket - int server_port = 4001; - // Use blocking sockets - int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + // Prepare server socket + int server_port = 4001; + // Use blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); - // Bind server to socket - struct sockaddr_in server_address; - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - server_address.sin_port = htons(server_port); - TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr *)&server_address, + sizeof(server_address)) != -1); - // Listen on socket - char buffer[BUFSIZE]; - socklen_t client_len = sizeof(struct sockaddr_in); - int client_socket_fd; - struct sockaddr_in client_address; - int32_t bytes_read = 0, total_bytes_read = 0; - TEST(listen(server_socket_fd, 1) != -1); + // Listen on socket + char buffer[BUFSIZE]; + socklen_t client_len = sizeof(struct sockaddr_in); + int client_socket_fd; + struct sockaddr_in client_address; + int32_t bytes_read = 0, total_bytes_read = 0; + TEST(listen(server_socket_fd, 1) != -1); - // Server accepts connection - client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_address, &client_len); - TEST(client_socket_fd != -1); + // Server accepts connection + client_socket_fd = + accept(server_socket_fd, (struct sockaddr *)&client_address, &client_len); + TEST(client_socket_fd != -1); - // Server waits for input and echoes message back to client - // The server shuts down after the client closes the connection - while ((bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0)) > 0) { - total_bytes_read += bytes_read; - // Echo back the data received from the client - send(client_socket_fd, buffer, bytes_read, 0); - } + // Server waits for input and echoes message back to client + // The server shuts down after the client closes the connection + while ((bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0)) > 0) { + total_bytes_read += bytes_read; + // Echo back the data received from the client + send(client_socket_fd, buffer, bytes_read, 0); + } - TEST(total_bytes_read > 0); + TEST(total_bytes_read > 0); - close(client_socket_fd); - close(server_socket_fd); + close(client_socket_fd); + close(server_socket_fd); } -int main() -{ - run_tcp_server(); +int main() { + run_tcp_server(); - return t_status; + return t_status; }