summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/sbc_harness/main.c22
-rw-r--r--lib9p/include/lib9p/srv.h2
-rw-r--r--lib9p/srv.c24
-rw-r--r--lib9p/tests/test_server/main.c4
-rw-r--r--libdhcp/dhcp_client.c45
-rw-r--r--libdhcp/include/libdhcp/client.h4
-rw-r--r--libhw/host_include/libhw/host_net.h11
-rw-r--r--libhw/host_net.c89
-rw-r--r--libhw/rp2040_include/libhw/w5500.h12
-rw-r--r--libhw/w5500.c136
-rw-r--r--libhw/w5500_ll.h1
-rw-r--r--libhw_generic/include/libhw/generic/net.h188
12 files changed, 198 insertions, 340 deletions
diff --git a/cmd/sbc_harness/main.c b/cmd/sbc_harness/main.c
index 7b1d5c5..ce80711 100644
--- a/cmd/sbc_harness/main.c
+++ b/cmd/sbc_harness/main.c
@@ -15,7 +15,6 @@
#include <libhw/rp2040_hwtimer.h>
#include <libhw/w5500.h>
#include <libmisc/hash.h>
-#include <libmisc/vcall.h>
#include <libusb/usb_common.h>
#include <libdhcp/client.h>
#include <lib9p/srv.h>
@@ -43,15 +42,6 @@ static COROUTINE hello_world_cr(void *_chan) {
cr_end();
}
-static COROUTINE dhcp_cr(void *_chip) {
- struct w5500 *chip = _chip;
- cr_begin();
-
- dhcp_client_main(chip, "harness");
-
- cr_end();
-}
-
struct {
struct rp2040_hwspi dev_spi;
struct w5500 dev_w5500;
@@ -60,11 +50,19 @@ struct {
struct lib9p_srv srv;
} globals;
+static COROUTINE dhcp_cr(void *) {
+ cr_begin();
+
+ dhcp_client_main(lo_box_w5500_if_as_net_iface(&globals.dev_w5500), "harness");
+
+ cr_end();
+}
+
static COROUTINE read9p_cr(void *) {
cr_begin();
lib9p_srv_read_cr(&globals.srv,
- VCALL(&globals.dev_w5500, tcp_listen, CONFIG_9P_PORT));
+ LO_CALL(lo_box_w5500_if_as_net_iface(&globals.dev_w5500), tcp_listen, CONFIG_9P_PORT));
cr_end();
}
@@ -120,7 +118,7 @@ COROUTINE init_cr(void *) {
coroutine_add("usb_common", usb_common_cr, NULL);
coroutine_add("usb_keyboard", usb_keyboard_cr, &globals.keyboard_chan);
coroutine_add("hello_world", hello_world_cr, &globals.keyboard_chan);
- coroutine_add_with_stack_size(4*1024, "dhcp", dhcp_cr, &globals.dev_w5500);
+ coroutine_add_with_stack_size(4*1024, "dhcp", dhcp_cr, NULL);
for (int i = 0; i < _CONFIG_9P_NUM_SOCKS; i++) {
char name[] = {'r', 'e', 'a', 'd', '-', hexdig[i], '\0'};
coroutine_add(name, read9p_cr, NULL);
diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h
index e9d2d7b..0fc9011 100644
--- a/lib9p/include/lib9p/srv.h
+++ b/lib9p/include/lib9p/srv.h
@@ -105,7 +105,7 @@ struct lib9p_srv {
* @errno LINUX_ERANGE R-message does not fit into max_msg_size
*/
-[[noreturn]] void lib9p_srv_read_cr(struct lib9p_srv *srv, implements_net_stream_listener *listener);
+[[noreturn]] void lib9p_srv_read_cr(struct lib9p_srv *srv, lo_interface net_stream_listener listener);
COROUTINE lib9p_srv_write_cr(void *_srv);
#endif /* _LIB9P_SRV_H_ */
diff --git a/lib9p/srv.c b/lib9p/srv.c
index 47dd78d..0bfe5da 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -108,7 +108,7 @@ struct _srv_fidinfo {
struct _srv_conn {
/* immutable */
struct lib9p_srv *parent_srv;
- implements_net_stream_conn *fd;
+ lo_interface net_stream_conn fd;
cid_t reader; /* the lib9p_srv_read_cr() coroutine */
/* mutable */
cr_mutex_t writelock;
@@ -197,7 +197,7 @@ static void respond_error(struct _lib9p_srv_req *req) {
&host, req->net_bytes);
cr_mutex_lock(&sess->parent_conn->writelock);
- r = VCALL(sess->parent_conn->fd, write,
+ r = LO_CALL(sess->parent_conn->fd, write,
req->net_bytes, uint32le_decode(req->net_bytes));
cr_mutex_unlock(&sess->parent_conn->writelock);
if (r < 0)
@@ -206,12 +206,12 @@ static void respond_error(struct _lib9p_srv_req *req) {
/* read coroutine *************************************************************/
-static bool read_at_least(implements_net_stream_conn *fd, uint8_t *buf, size_t goal, size_t *done) {
+static bool read_at_least(lo_interface net_stream_conn fd, uint8_t *buf, size_t goal, size_t *done) {
assert(buf);
assert(goal);
assert(done);
while (*done < goal) {
- ssize_t r = VCALL(fd, read, &buf[*done], CONFIG_9P_MAX_MSG_SIZE - *done);
+ ssize_t r = LO_CALL(fd, read, &buf[*done], CONFIG_9P_MAX_MSG_SIZE - *done);
if (r < 0) {
nonrespond_errorf("read: %s", net_strerror(-r));
return true;
@@ -227,12 +227,12 @@ static bool read_at_least(implements_net_stream_conn *fd, uint8_t *buf, size_t g
static void handle_message(struct _lib9p_srv_req *ctx);
-[[noreturn]] void lib9p_srv_read_cr(struct lib9p_srv *srv, implements_net_stream_listener *listener) {
+[[noreturn]] void lib9p_srv_read_cr(struct lib9p_srv *srv, lo_interface net_stream_listener listener) {
uint8_t buf[CONFIG_9P_MAX_MSG_SIZE];
assert(srv);
assert(srv->rootdir);
- assert(listener);
+ assert(!LO_IS_NULL(listener));
srv->readers++;
@@ -241,10 +241,10 @@ static void handle_message(struct _lib9p_srv_req *ctx);
for (;;) {
struct _srv_conn conn = {
.parent_srv = srv,
- .fd = VCALL(listener, accept),
+ .fd = LO_CALL(listener, accept),
.reader = cr_getcid(),
};
- if (!conn.fd) {
+ if (LO_IS_NULL(conn.fd)) {
nonrespond_errorf("accept: error");
srv->readers--;
if (srv->readers == 0)
@@ -305,12 +305,12 @@ static void handle_message(struct _lib9p_srv_req *ctx);
_lib9p_srv_reqch_send_req(&srv->_reqch, &req);
}
close:
- VCALL(conn.fd, close, true, sess.reqs.len == 0);
+ LO_CALL(conn.fd, close, true, sess.reqs.len == 0);
if (sess.reqs.len) {
sess.closing = true;
cr_pause_and_yield();
assert(sess.reqs.len == 0);
- VCALL(conn.fd, close, true, true);
+ LO_CALL(conn.fd, close, true, true);
}
}
}
@@ -438,8 +438,8 @@ static void handle_message(struct _lib9p_srv_req *ctx) {
goto write;
cr_mutex_lock(&ctx->parent_sess->parent_conn->writelock);
- VCALL(ctx->parent_sess->parent_conn->fd, write,
- ctx->net_bytes, uint32le_decode(ctx->net_bytes));
+ LO_CALL(ctx->parent_sess->parent_conn->fd, write,
+ ctx->net_bytes, uint32le_decode(ctx->net_bytes));
cr_mutex_unlock(&ctx->parent_sess->parent_conn->writelock);
}
}
diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c
index 8df3da0..6655f67 100644
--- a/lib9p/tests/test_server/main.c
+++ b/lib9p/tests/test_server/main.c
@@ -91,7 +91,7 @@ static uint32_t api_pwrite(implements_lib9p_srv_file *, struct lib9p_srv_ctx *,
if (byte_count == 0)
return 0;
for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++)
- VCALL(&globals.listeners[i], close);
+ LO_CALL(lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i]), close);
return byte_count;
}
@@ -170,7 +170,7 @@ static COROUTINE read_cr(void *_i) {
hostnet_tcp_listener_init(&globals.listeners[i], 9000);
- lib9p_srv_read_cr(&globals.srv, &globals.listeners[i]);
+ lib9p_srv_read_cr(&globals.srv, lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i]));
cr_end();
}
diff --git a/libdhcp/dhcp_client.c b/libdhcp/dhcp_client.c
index d6b2f19..e50c5f3 100644
--- a/libdhcp/dhcp_client.c
+++ b/libdhcp/dhcp_client.c
@@ -87,7 +87,6 @@
#include <string.h> /* for strlen(), memcpy(), memset() */
#include <libmisc/rand.h>
-#include <libmisc/vcall.h>
#include <libhw/generic/alarmclock.h>
#define LOG_NAME DHCP
@@ -125,8 +124,8 @@ enum requirement {
struct dhcp_client {
/* Static. */
- implements_net_iface *iface;
- implements_net_packet_conn *sock;
+ lo_interface net_iface iface;
+ lo_interface net_packet_conn sock;
struct net_eth_addr self_eth_addr;
char *self_hostname;
size_t self_id_len;
@@ -462,7 +461,7 @@ static bool dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const c
* Send *
\**********************************************************************/
debugf("state %s: sending DHCP %s", state_strs[client->state], dhcp_msgtyp_str(msgtyp));
- ssize_t r = VCALL(client->sock, sendto, scratch_msg, DHCP_MSG_BASE_SIZE + optlen,
+ ssize_t r = LO_CALL(client->sock, sendto, scratch_msg, DHCP_MSG_BASE_SIZE + optlen,
client_broadcasts ? net_ip4_addr_broadcast : client->lease_server_id, DHCP_PORT_SERVER);
if (r < 0) {
debugf("error: sendto: %zd", r);
@@ -579,7 +578,7 @@ static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg
assert(client);
ignore:
- msg_len = VCALL(client->sock, recvfrom, &ret->raw, sizeof(ret->raw), &srv_addr, &srv_port);
+ msg_len = LO_CALL(client->sock, recvfrom, &ret->raw, sizeof(ret->raw), &srv_addr, &srv_port);
if (msg_len < 0)
/* msg_len is -errno */
return msg_len;
@@ -702,9 +701,9 @@ static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg
}
/** @return true if there's a conflict, false if the addr appears to be unused */
-static bool dhcp_check_conflict(implements_net_packet_conn *sock, struct net_ip4_addr addr) {
- assert(sock);
- ssize_t v = VCALL(sock, sendto, "CHECK_IP_CONFLICT", 17, addr, 5000);
+static bool dhcp_check_conflict(lo_interface net_packet_conn sock, struct net_ip4_addr addr) {
+ assert(!LO_IS_NULL(sock));
+ ssize_t v = LO_CALL(sock, sendto, "CHECK_IP_CONFLICT", 17, addr, 5000);
debugf("check_ip_conflict => %zd", v);
return v != -NET_EARP_TIMEOUT;
}
@@ -745,7 +744,7 @@ static void dhcp_client_take_lease(struct dhcp_client *client, struct dhcp_recv_
infof(":: addr = "PRI_net_ip4_addr, ARG_net_ip4_addr(client->lease_client_addr));
infof(":: gateway_addr = "PRI_net_ip4_addr, ARG_net_ip4_addr(client->lease_auxdata.gateway_addr));
infof(":: subnet_mask = "PRI_net_ip4_addr, ARG_net_ip4_addr(client->lease_auxdata.subnet_mask));
- VCALL(client->iface, ifup, (struct net_iface_config){
+ LO_CALL(client->iface, ifup, (struct net_iface_config){
.addr = client->lease_client_addr,
.gateway_addr = client->lease_auxdata.gateway_addr,
.subnet_mask = client->lease_auxdata.subnet_mask,
@@ -776,7 +775,7 @@ static void dhcp_client_setstate(struct dhcp_client *client,
dhcp_client_setstate(client, STATE_SELECTING, DHCP_MSGTYP_DISCOVER, NULL, scratch_msg);
break;
case STATE_SELECTING:
- VCALL(client->sock, set_read_deadline, client->time_ns_init+CONFIG_DHCP_SELECTING_NS);
+ LO_CALL(client->sock, set_read_deadline, client->time_ns_init+CONFIG_DHCP_SELECTING_NS);
switch ((r = dhcp_client_recv(client, scratch_msg))) {
case 0:
switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
@@ -798,7 +797,7 @@ static void dhcp_client_setstate(struct dhcp_client *client,
}
break;
case STATE_REQUESTING:
- VCALL(client->sock, set_read_deadline, 0);
+ LO_CALL(client->sock, set_read_deadline, 0);
switch ((r = dhcp_client_recv(client, scratch_msg))) {
case 0:
switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
@@ -825,7 +824,7 @@ static void dhcp_client_setstate(struct dhcp_client *client,
}
break;
case STATE_BOUND:
- VCALL(client->sock, set_read_deadline, client->lease_time_ns_t1);
+ LO_CALL(client->sock, set_read_deadline, client->lease_time_ns_t1);
switch ((r = dhcp_client_recv(client, scratch_msg))) {
case 0:
/* discard */
@@ -842,12 +841,12 @@ static void dhcp_client_setstate(struct dhcp_client *client,
client->xid = rand_uint63n(UINT32_MAX);
client->time_ns_init = LO_CALL(bootclock, get_time_ns);
- VCALL(client->sock, set_read_deadline, client->lease_time_ns_t2);
+ LO_CALL(client->sock, set_read_deadline, client->lease_time_ns_t2);
switch ((r = dhcp_client_recv(client, scratch_msg))) {
case 0:
switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_NAK:
- VCALL(client->iface, ifdown);
+ LO_CALL(client->iface, ifdown);
dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
break;
case DHCP_MSGTYP_ACK:
@@ -868,12 +867,12 @@ static void dhcp_client_setstate(struct dhcp_client *client,
}
break;
case STATE_REBINDING:
- VCALL(client->sock, set_read_deadline, client->lease_time_ns_end);
+ LO_CALL(client->sock, set_read_deadline, client->lease_time_ns_end);
switch ((r = dhcp_client_recv(client, scratch_msg))) {
case 0:
switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_NAK:
- VCALL(client->iface, ifdown);
+ LO_CALL(client->iface, ifdown);
dhcp_client_setstate(client, STATE_BOUND, 0, NULL, scratch_msg);
break;
case DHCP_MSGTYP_ACK:
@@ -885,7 +884,7 @@ static void dhcp_client_setstate(struct dhcp_client *client,
}
break;
case -NET_ERECV_TIMEOUT:
- VCALL(client->iface, ifdown);
+ LO_CALL(client->iface, ifdown);
dhcp_client_setstate(client, STATE_BOUND, 0, NULL, scratch_msg);
break;
default:
@@ -902,9 +901,9 @@ static void dhcp_client_setstate(struct dhcp_client *client,
}
}
-[[noreturn]] void dhcp_client_main(implements_net_iface *iface,
+[[noreturn]] void dhcp_client_main(lo_interface net_iface iface,
char *self_hostname) {
- assert(iface);
+ assert(!LO_IS_NULL(iface));
/* Even though a client ID is optional and not meaningful for
* us (the best we can do is to duplicate .chaddr), systemd's
@@ -912,14 +911,14 @@ static void dhcp_client_setstate(struct dhcp_client *client,
* require it to be set. */
struct {uint8_t typ; struct net_eth_addr dat;} client_id = {
DHCP_HTYPE_ETHERNET,
- VCALL(iface, hwaddr),
+ LO_CALL(iface, hwaddr),
};
struct dhcp_client client = {
/* Static. */
.iface = iface,
- .sock = VCALL(iface, udp_conn, DHCP_PORT_CLIENT),
- .self_eth_addr = VCALL(iface, hwaddr),
+ .sock = LO_CALL(iface, udp_conn, DHCP_PORT_CLIENT),
+ .self_eth_addr = LO_CALL(iface, hwaddr),
.self_hostname = self_hostname,
.self_id_len = sizeof(client_id),
.self_id_dat = &client_id,
@@ -927,7 +926,7 @@ static void dhcp_client_setstate(struct dhcp_client *client,
/* Mutable. */
.state = STATE_INIT,
};
- assert(client.sock);
+ assert(!LO_IS_NULL(client.sock));
struct dhcp_recv_msg scratch;
diff --git a/libdhcp/include/libdhcp/client.h b/libdhcp/include/libdhcp/client.h
index c3cb76f..f81e9b1 100644
--- a/libdhcp/include/libdhcp/client.h
+++ b/libdhcp/include/libdhcp/client.h
@@ -1,6 +1,6 @@
/* libdhcp/client.h - A DHCP client
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@@ -69,7 +69,7 @@
#include <libhw/generic/net.h>
-[[noreturn]] void dhcp_client_main(implements_net_iface *iface,
+[[noreturn]] void dhcp_client_main(lo_interface net_iface iface,
char *self_hostname);
#endif /* _LIBDHCP_CLIENT_H_ */
diff --git a/libhw/host_include/libhw/host_net.h b/libhw/host_include/libhw/host_net.h
index bfef5c9..fced229 100644
--- a/libhw/host_include/libhw/host_net.h
+++ b/libhw/host_include/libhw/host_net.h
@@ -1,6 +1,6 @@
/* libhw/host_net.h - <libhw/generic/net.h> implementation for hosted glibc
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -14,33 +14,30 @@
#include <libhw/generic/net.h>
struct _hostnet_tcp_conn {
- implements_net_stream_conn;
-
BEGIN_PRIVATE(LIBHW_HOST_NET_H)
int fd;
uint64_t read_deadline_ns;
END_PRIVATE(LIBHW_HOST_NET_H)
};
+LO_IMPLEMENTATION_H(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp)
struct hostnet_tcp_listener {
- implements_net_stream_listener;
-
BEGIN_PRIVATE(LIBHW_HOST_NET_H)
int fd;
struct _hostnet_tcp_conn active_conn;
END_PRIVATE(LIBHW_HOST_NET_H)
};
+LO_IMPLEMENTATION_H(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist)
void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port);
struct hostnet_udp_conn {
- implements_net_packet_conn;
-
BEGIN_PRIVATE(LIBHW_HOST_NET_H)
int fd;
uint64_t read_deadline_ns;
END_PRIVATE(LIBHW_HOST_NET_H)
};
+LO_IMPLEMENTATION_H(net_packet_conn, struct hostnet_udp_conn, hostnet_udp)
void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port);
diff --git a/libhw/host_net.c b/libhw/host_net.c
index 3352b87..505c7dc 100644
--- a/libhw/host_net.c
+++ b/libhw/host_net.c
@@ -21,7 +21,7 @@
#include <libcr/coroutine.h>
#include <libmisc/assert.h>
#include <libmisc/macro.h>
-#include <libmisc/vcall.h>
+#include <libobj/obj.h>
#include <libhw/generic/alarmclock.h>
@@ -30,6 +30,10 @@
#include "host_util.h" /* for host_sigrt_alloc(), ns_to_host_us_time() */
+LO_IMPLEMENTATION_C(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp, static)
+LO_IMPLEMENTATION_C(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist, static)
+LO_IMPLEMENTATION_C(net_packet_conn, struct hostnet_udp_conn, hostnet_udp, static)
+
/* common *********************************************************************/
static int hostnet_sig_io = 0;
@@ -109,25 +113,6 @@ static inline ssize_t hostnet_map_negerrno(ssize_t v, enum hostnet_timeout_op op
/* TCP init() ( AKA socket(3) + listen(3) )************************************/
-static implements_net_stream_conn *hostnet_tcplist_accept(implements_net_stream_listener *);
-static int hostnet_tcplist_close(implements_net_stream_listener *);
-static void hostnet_tcp_set_read_deadline(implements_net_stream_conn *conn, uint64_t ts_ns);
-static ssize_t hostnet_tcp_read(implements_net_stream_conn *conn, void *buf, size_t count);
-static ssize_t hostnet_tcp_write(implements_net_stream_conn *conn, void *buf, size_t count);
-static int hostnet_tcp_close(implements_net_stream_conn *conn, bool rd, bool wr);
-
-static struct net_stream_listener_vtable hostnet_tcp_listener_vtable = {
- .accept = hostnet_tcplist_accept,
- .close = hostnet_tcplist_close,
-};
-
-static struct net_stream_conn_vtable hostnet_tcp_conn_vtable = {
- .set_read_deadline = hostnet_tcp_set_read_deadline,
- .read = hostnet_tcp_read,
- .write = hostnet_tcp_write,
- .close = hostnet_tcp_close,
-};
-
void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port) {
int listenerfd;
union {
@@ -151,7 +136,6 @@ void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port)
if (listen(listenerfd, 0) < 0)
error(1, errno, "listen(fd=%d)", listenerfd);
- self->vtable = &hostnet_tcp_listener_vtable;
self->fd = listenerfd;
}
@@ -175,9 +159,7 @@ static void *hostnet_pthread_accept(void *_args) {
return NULL;
}
-static implements_net_stream_conn *hostnet_tcplist_accept(implements_net_stream_listener *_listener) {
- struct hostnet_tcp_listener *listener =
- VCALL_SELF(struct hostnet_tcp_listener, implements_net_stream_listener, _listener);
+static lo_interface net_stream_conn hostnet_tcplist_accept(struct hostnet_tcp_listener *listener) {
assert(listener);
int ret_connfd;
@@ -188,22 +170,19 @@ static implements_net_stream_conn *hostnet_tcplist_accept(implements_net_stream_
.ret_connfd = &ret_connfd,
};
if (RUN_PTHREAD(hostnet_pthread_accept, &args))
- return NULL;
+ return LO_NULL(net_stream_conn);
if (ret_connfd < 0)
- return NULL;
+ return LO_NULL(net_stream_conn);
- listener->active_conn.vtable = &hostnet_tcp_conn_vtable;
listener->active_conn.fd = ret_connfd;
listener->active_conn.read_deadline_ns = 0;
- return &listener->active_conn;
+ return lo_box_hostnet_tcp_as_net_stream_conn(&listener->active_conn);
}
/* TCP listener close() *******************************************************/
-static int hostnet_tcplist_close(implements_net_stream_listener *_listener) {
- struct hostnet_tcp_listener *listener =
- VCALL_SELF(struct hostnet_tcp_listener, implements_net_stream_listener, _listener);
+static int hostnet_tcplist_close(struct hostnet_tcp_listener *listener) {
assert(listener);
return hostnet_map_negerrno(shutdown(listener->fd, SHUT_RDWR) ? -errno : 0, OP_NONE);
@@ -211,9 +190,7 @@ static int hostnet_tcplist_close(implements_net_stream_listener *_listener) {
/* TCP read() *****************************************************************/
-static void hostnet_tcp_set_read_deadline(implements_net_stream_conn *_conn, uint64_t ts_ns) {
- struct _hostnet_tcp_conn *conn =
- VCALL_SELF(struct _hostnet_tcp_conn, implements_net_stream_conn, _conn);
+static void hostnet_tcp_set_read_deadline(struct _hostnet_tcp_conn *conn, uint64_t ts_ns) {
assert(conn);
conn->read_deadline_ns = ts_ns;
@@ -250,9 +227,7 @@ static void *hostnet_pthread_read(void *_args) {
return NULL;
}
-static ssize_t hostnet_tcp_read(implements_net_stream_conn *_conn, void *buf, size_t count) {
- struct _hostnet_tcp_conn *conn =
- VCALL_SELF(struct _hostnet_tcp_conn, implements_net_stream_conn, _conn);
+static ssize_t hostnet_tcp_read(struct _hostnet_tcp_conn *conn, void *buf, size_t count) {
assert(conn);
ssize_t ret;
@@ -310,9 +285,7 @@ static void *hostnet_pthread_write(void *_args) {
return NULL;
}
-static ssize_t hostnet_tcp_write(implements_net_stream_conn *_conn, void *buf, size_t count) {
- struct _hostnet_tcp_conn *conn =
- VCALL_SELF(struct _hostnet_tcp_conn, implements_net_stream_conn, _conn);
+static ssize_t hostnet_tcp_write(struct _hostnet_tcp_conn *conn, void *buf, size_t count) {
assert(conn);
ssize_t ret;
@@ -333,9 +306,7 @@ static ssize_t hostnet_tcp_write(implements_net_stream_conn *_conn, void *buf, s
/* TCP close() ****************************************************************/
-static int hostnet_tcp_close(implements_net_stream_conn *_conn, bool rd, bool wr) {
- struct _hostnet_tcp_conn *conn =
- VCALL_SELF(struct _hostnet_tcp_conn, implements_net_stream_conn, _conn);
+static int hostnet_tcp_close(struct _hostnet_tcp_conn *conn, bool rd, bool wr) {
assert(conn);
int how;
@@ -352,21 +323,6 @@ static int hostnet_tcp_close(implements_net_stream_conn *_conn, bool rd, bool wr
/* UDP init() *****************************************************************/
-static void hostnet_udp_set_read_deadline(implements_net_packet_conn *self,
- uint64_t ts_ns);
-static ssize_t hostnet_udp_sendto(implements_net_packet_conn *self, void *buf, size_t len,
- struct net_ip4_addr addr, uint16_t port);
-static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *self, void *buf, size_t len,
- struct net_ip4_addr *ret_addr, uint16_t *ret_port);
-static int hostnet_udp_close(implements_net_packet_conn *self);
-
-static struct net_packet_conn_vtable hostnet_udp_conn_vtable = {
- .set_read_deadline = hostnet_udp_set_read_deadline,
- .sendto = hostnet_udp_sendto,
- .recvfrom = hostnet_udp_recvfrom,
- .close = hostnet_udp_close,
-};
-
void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port) {
int fd;
union {
@@ -385,7 +341,6 @@ void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port) {
if (bind(fd, &addr.gen, sizeof addr) < 0)
error(1, errno, "bind");
- self->vtable = &hostnet_udp_conn_vtable;
self->fd = fd;
self->read_deadline_ns = 0;
}
@@ -427,10 +382,8 @@ static void *hostnet_pthread_sendto(void *_args) {
return NULL;
}
-static ssize_t hostnet_udp_sendto(implements_net_packet_conn *_conn, void *buf, size_t count,
+static ssize_t hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size_t count,
struct net_ip4_addr node, uint16_t port) {
- struct hostnet_udp_conn *conn =
- VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
assert(conn);
ssize_t ret;
@@ -453,10 +406,8 @@ static ssize_t hostnet_udp_sendto(implements_net_packet_conn *_conn, void *buf,
/* UDP recvfrom() *************************************************************/
-static void hostnet_udp_set_read_deadline(implements_net_packet_conn *_conn,
+static void hostnet_udp_set_read_deadline(struct hostnet_udp_conn *conn,
uint64_t ts_ns) {
- struct hostnet_udp_conn *conn =
- VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
assert(conn);
conn->read_deadline_ns = ts_ns;
@@ -514,10 +465,8 @@ static void *hostnet_pthread_recvfrom(void *_args) {
return NULL;
}
-static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *_conn, void *buf, size_t count,
+static ssize_t hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, size_t count,
struct net_ip4_addr *ret_node, uint16_t *ret_port) {
- struct hostnet_udp_conn *conn =
- VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
assert(conn);
ssize_t ret;
@@ -549,9 +498,7 @@ static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *_conn, void *buf
/* UDP close() ****************************************************************/
-static int hostnet_udp_close(implements_net_packet_conn *_conn) {
- struct hostnet_udp_conn *conn =
- VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
+static int hostnet_udp_close(struct hostnet_udp_conn *conn) {
assert(conn);
return hostnet_map_negerrno(close(conn->fd) ? -errno : 0, OP_NONE);
diff --git a/libhw/rp2040_include/libhw/w5500.h b/libhw/rp2040_include/libhw/w5500.h
index 87d333a..ab9f50e 100644
--- a/libhw/rp2040_include/libhw/w5500.h
+++ b/libhw/rp2040_include/libhw/w5500.h
@@ -20,11 +20,8 @@
CR_CHAN_DECLARE(_w5500_sockintr_ch, uint8_t)
struct _w5500_socket {
- /* const-after-init */
- implements_net_stream_listener implements_net_stream_listener;
- implements_net_stream_conn implements_net_stream_conn;
- implements_net_packet_conn implements_net_packet_conn;
BEGIN_PRIVATE(LIBHW_W5500_H)
+ /* const-after-init */
uint8_t socknum;
/* mutable */
@@ -43,11 +40,13 @@ struct _w5500_socket {
END_PRIVATE(LIBHW_W5500_H)
};
+LO_IMPLEMENTATION_H(net_stream_listener, struct _w5500_socket, w5500_tcplist)
+LO_IMPLEMENTATION_H(net_stream_conn, struct _w5500_socket, w5500_tcp)
+LO_IMPLEMENTATION_H(net_packet_conn, struct _w5500_socket, w5500_udp)
struct w5500 {
- /* const-after-init */
- implements_net_iface;
BEGIN_PRIVATE(LIBHW_W5500_H)
+ /* const-after-init */
lo_interface spi spidev;
uint pin_intr;
uint pin_reset;
@@ -61,6 +60,7 @@ struct w5500 {
cr_mutex_t mu;
END_PRIVATE(LIBHW_W5500_H)
};
+LO_IMPLEMENTATION_H(net_iface, struct w5500, w5500_if)
/**
* Initialize a WIZnet W5500 Ethernet-and-TCP/IP-offload chip.
diff --git a/libhw/w5500.c b/libhw/w5500.c
index 2c130f5..dfe169f 100644
--- a/libhw/w5500.c
+++ b/libhw/w5500.c
@@ -74,7 +74,6 @@
#include <hardware/gpio.h> /* pico-sdk:hardware_gpio */
#include <libcr/coroutine.h> /* for cr_yield() */
-#include <libmisc/vcall.h> /* for VCALL_SELF() */
#include <libhw/generic/alarmclock.h> /* for sleep_*() */
@@ -124,61 +123,12 @@ static const char *w5500_state_str(uint8_t state) {
}
}
-/* vtables ********************************************************************/
-
-/* iface */
-static struct net_eth_addr w5500_if_hwaddr (implements_net_iface *);
-static void w5500_if_up (implements_net_iface *, struct net_iface_config);
-static void w5500_if_down (implements_net_iface *);
-static implements_net_stream_listener *w5500_if_tcp_listen (implements_net_iface *, uint16_t local_port);
-static implements_net_stream_conn *w5500_if_tcp_dial (implements_net_iface *, struct net_ip4_addr, uint16_t remote_port);
-static implements_net_packet_conn *w5500_if_udp_conn (implements_net_iface *, uint16_t local_port);
-
-/* stream_listener */
-static implements_net_stream_conn *w5500_tcplist_accept(implements_net_stream_listener *);
-static int w5500_tcplist_close (implements_net_stream_listener *);
-
-/* stream_conn */
-static void w5500_tcp_set_read_deadline (implements_net_stream_conn *, uint64_t ns);
-static ssize_t w5500_tcp_read (implements_net_stream_conn *, void *, size_t);
-static ssize_t w5500_tcp_write (implements_net_stream_conn *, void *, size_t);
-static int w5500_tcp_close (implements_net_stream_conn *, bool rd, bool wr);
-
-/* packet_conn */
-static void w5500_udp_set_read_deadline (implements_net_packet_conn *, uint64_t ns);
-static ssize_t w5500_udp_recvfrom (implements_net_packet_conn *, void *, size_t, struct net_ip4_addr *, uint16_t *);
-static ssize_t w5500_udp_sendto (implements_net_packet_conn *, void *, size_t, struct net_ip4_addr, uint16_t);
-static int w5500_udp_close (implements_net_packet_conn *);
-
-/* tables */
-
-static struct net_iface_vtable w5500_iface_vtable = {
- .hwaddr = w5500_if_hwaddr,
- .ifup = w5500_if_up,
- .ifdown = w5500_if_down,
- .tcp_listen = w5500_if_tcp_listen,
- .tcp_dial = w5500_if_tcp_dial,
- .udp_conn = w5500_if_udp_conn,
-};
-
-static struct net_stream_listener_vtable w5500_tcp_listener_vtable = {
- .accept = w5500_tcplist_accept,
- .close = w5500_tcplist_close,
-};
-
-static struct net_stream_conn_vtable w5500_tcp_conn_vtable = {
- .set_read_deadline = w5500_tcp_set_read_deadline,
- .read = w5500_tcp_read,
- .write = w5500_tcp_write,
- .close = w5500_tcp_close,
-};
-
-static struct net_packet_conn_vtable w5500_udp_conn_vtable = {
- .set_read_deadline = w5500_udp_set_read_deadline,
- .recvfrom = w5500_udp_recvfrom,
- .sendto = w5500_udp_sendto,
- .close = w5500_udp_close,
-};
+/* libobj *********************************************************************/
+
+LO_IMPLEMENTATION_C(net_stream_listener, struct _w5500_socket, w5500_tcplist, static)
+LO_IMPLEMENTATION_C(net_stream_conn, struct _w5500_socket, w5500_tcp, static)
+LO_IMPLEMENTATION_C(net_packet_conn, struct _w5500_socket, w5500_udp, static)
+LO_IMPLEMENTATION_C(net_iface, struct w5500, w5500_if, static)
/* mid-level utilities ********************************************************/
@@ -311,9 +261,6 @@ static inline void w5500_socket_close(struct _w5500_socket *socket) {
}
#define ASSERT_SELF(_iface, _mode) \
- struct _w5500_socket *socket = \
- VCALL_SELF(struct _w5500_socket, \
- implements_net_##_iface, _socket); \
assert(socket); \
uint8_t socknum = socket->socknum; \
assert(socknum < 8); \
@@ -341,7 +288,6 @@ void _w5500_init(struct w5500 *chip,
/* Initialize the data structures. */
*chip = (struct w5500){
/* const-after-init */
- .implements_net_iface = { .vtable = &w5500_iface_vtable },
.spidev = spi,
.pin_intr = pin_intr,
.pin_reset = pin_reset,
@@ -353,9 +299,6 @@ void _w5500_init(struct w5500 *chip,
for (uint8_t i = 0; i < 8; i++) {
chip->sockets[i] = (struct _w5500_socket){
/* const-after-init */
- .implements_net_stream_listener = { .vtable = &w5500_tcp_listener_vtable },
- .implements_net_stream_conn = { .vtable = &w5500_tcp_conn_vtable },
- .implements_net_packet_conn = { .vtable = &w5500_udp_conn_vtable },
.socknum = i,
/* mutable */
.next_free = (i + 1 < 8) ? &chip->sockets[i+1] : NULL,
@@ -449,15 +392,13 @@ void w5500_soft_reset(struct w5500 *chip) {
cr_mutex_unlock(&chip->mu);
}
-static struct net_eth_addr w5500_if_hwaddr(implements_net_iface *_chip) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static struct net_eth_addr w5500_if_hwaddr(struct w5500 *chip) {
assert(chip);
return chip->hwaddr;
}
-static void _w5500_if_up(implements_net_iface *_chip, struct net_iface_config cfg) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static void _w5500_if_up(struct w5500 *chip, struct net_iface_config cfg) {
assert(chip);
cr_mutex_lock(&chip->mu);
@@ -469,27 +410,26 @@ static void _w5500_if_up(implements_net_iface *_chip, struct net_iface_config cf
cr_mutex_unlock(&chip->mu);
}
-static void w5500_if_up(implements_net_iface *_chip, struct net_iface_config cfg) {
+static void w5500_if_ifup(struct w5500 *chip, struct net_iface_config cfg) {
debugf("if_up()");
debugf(":: addr = "PRI_net_ip4_addr, ARG_net_ip4_addr(cfg.addr));
debugf(":: gateway_addr = "PRI_net_ip4_addr, ARG_net_ip4_addr(cfg.gateway_addr));
debugf(":: subnet_mask = "PRI_net_ip4_addr, ARG_net_ip4_addr(cfg.subnet_mask));
- _w5500_if_up(_chip, cfg);
+ _w5500_if_up(chip, cfg);
}
-static void w5500_if_down(implements_net_iface *_chip) {
+static void w5500_if_ifdown(struct w5500 *chip) {
debugf("if_down()");
- _w5500_if_up(_chip, (struct net_iface_config){0});
+ _w5500_if_up(chip, (struct net_iface_config){0});
}
-static implements_net_stream_listener *w5500_if_tcp_listen(implements_net_iface *_chip, uint16_t local_port) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static lo_interface net_stream_listener w5500_if_tcp_listen(struct w5500 *chip, uint16_t local_port) {
assert(chip);
struct _w5500_socket *sock = w5500_alloc_socket(chip);
if (!sock) {
debugf("tcp_listen() => no sock");
- return NULL;
+ return LO_NULL(net_stream_listener);
}
debugf("tcp_listen() => sock[%"PRIu8"]", sock->socknum);
@@ -502,12 +442,11 @@ static implements_net_stream_listener *w5500_if_tcp_listen(implements_net_iface
sock->read_deadline_ns = 0;
sock->list_open = true;
- return &sock->implements_net_stream_listener;
+ return lo_box_w5500_tcplist_as_net_stream_listener(sock);
}
-static implements_net_stream_conn *w5500_if_tcp_dial(implements_net_iface *_chip,
- struct net_ip4_addr node, uint16_t port) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static lo_interface net_stream_conn w5500_if_tcp_dial(struct w5500 *chip,
+ struct net_ip4_addr node, uint16_t port) {
assert(chip);
assert(memcmp(node.octets, net_ip4_addr_zero.octets, 4));
assert(memcmp(node.octets, net_ip4_addr_broadcast.octets, 4));
@@ -516,7 +455,7 @@ static implements_net_stream_conn *w5500_if_tcp_dial(implements_net_iface *_chip
struct _w5500_socket *socket = w5500_alloc_socket(chip);
if (!socket) {
debugf("tcp_dial() => no sock");
- return NULL;
+ return LO_NULL(net_stream_conn);
}
uint8_t socknum = socket->socknum;
debugf("tcp_dial() => sock[%"PRIu8"]", socknum);
@@ -553,21 +492,20 @@ static implements_net_stream_conn *w5500_if_tcp_dial(implements_net_iface *_chip
cr_yield();
break;
case STATE_TCP_ESTABLISHED:
- return &socket->implements_net_stream_conn;
+ return lo_box_w5500_tcp_as_net_stream_conn(socket);
default:
goto restart;
}
}
}
-static implements_net_packet_conn *w5500_if_udp_conn(implements_net_iface *_chip, uint16_t local_port) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static lo_interface net_packet_conn w5500_if_udp_conn(struct w5500 *chip, uint16_t local_port) {
assert(chip);
struct _w5500_socket *socket = w5500_alloc_socket(chip);
if (!socket) {
debugf("udp_conn() => no sock");
- return NULL;
+ return LO_NULL(net_packet_conn);
}
uint8_t socknum = socket->socknum;
debugf("udp_conn() => sock[%"PRIu8"]", socknum);
@@ -590,18 +528,18 @@ static implements_net_packet_conn *w5500_if_udp_conn(implements_net_iface *_chip
cr_yield();
cr_mutex_unlock(&chip->mu);
- return &socket->implements_net_packet_conn;
+ return lo_box_w5500_udp_as_net_packet_conn(socket);
}
/* tcp_listener methods *******************************************************/
-static implements_net_stream_conn *w5500_tcplist_accept(implements_net_stream_listener *_socket) {
+static lo_interface net_stream_conn w5500_tcplist_accept(struct _w5500_socket *socket) {
ASSERT_SELF(stream_listener, TCP);
restart:
if (!socket->list_open) {
debugf("tcp_listener.accept() => already closed");
- return NULL;
+ return LO_NULL(net_stream_conn);
}
cr_mutex_lock(&chip->mu);
@@ -630,14 +568,14 @@ static implements_net_stream_conn *w5500_tcplist_accept(implements_net_stream_li
/* fall-through */
case STATE_TCP_CLOSE_WAIT:
socket->write_open = true;
- return &socket->implements_net_stream_conn;
+ return lo_box_w5500_tcp_as_net_stream_conn(socket);
default:
goto restart;
}
}
}
-static int w5500_tcplist_close(implements_net_stream_listener *_socket) {
+static int w5500_tcplist_close(struct _w5500_socket *socket) {
debugf("tcp_listener.close()");
ASSERT_SELF(stream_listener, TCP);
@@ -648,7 +586,7 @@ static int w5500_tcplist_close(implements_net_stream_listener *_socket) {
/* tcp_conn methods ***********************************************************/
-static ssize_t w5500_tcp_write(implements_net_stream_conn *_socket, void *buf, size_t count) {
+static ssize_t w5500_tcp_write(struct _w5500_socket *socket, void *buf, size_t count) {
debugf("tcp_conn.write(%zu)", count);
ASSERT_SELF(stream_conn, TCP);
assert(buf);
@@ -725,7 +663,7 @@ static ssize_t w5500_tcp_write(implements_net_stream_conn *_socket, void *buf, s
return done;
}
-static void w5500_tcp_set_read_deadline(implements_net_stream_conn *_socket, uint64_t ns) {
+static void w5500_tcp_set_read_deadline(struct _w5500_socket *socket, uint64_t ns) {
debugf("tcp_conn.set_read_deadline(%"PRIu64")", ns);
ASSERT_SELF(stream_conn, TCP);
socket->read_deadline_ns = ns;
@@ -736,7 +674,7 @@ static void w5500_tcp_alarm_handler(void *_arg) {
cr_sema_signal_from_intrhandler(&socket->read_sema);
}
-static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, size_t count) {
+static ssize_t w5500_tcp_read(struct _w5500_socket *socket, void *buf, size_t count) {
debugf("tcp_conn.read()");
ASSERT_SELF(stream_conn, TCP);
assert(buf);
@@ -745,9 +683,9 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
struct alarmclock_trigger trigger = {0};
if (socket->read_deadline_ns)
LO_CALL(bootclock, add_trigger, &trigger,
- socket->read_deadline_ns,
- w5500_tcp_alarm_handler,
- socket);
+ socket->read_deadline_ns,
+ w5500_tcp_alarm_handler,
+ socket);
/* Wait until there is data to read. */
uint16_t avail = 0;
@@ -806,7 +744,7 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
return avail;
}
-static int w5500_tcp_close(implements_net_stream_conn *_socket, bool rd, bool wr) {
+static int w5500_tcp_close(struct _w5500_socket *socket, bool rd, bool wr) {
debugf("tcp_conn.close(rd=%s, wr=%s)", rd ? "true" : "false", wr ? "true" : "false");
ASSERT_SELF(stream_conn, TCP);
@@ -839,7 +777,7 @@ static int w5500_tcp_close(implements_net_stream_conn *_socket, bool rd, bool wr
/* udp_conn methods ***********************************************************/
-static ssize_t w5500_udp_sendto(implements_net_packet_conn *_socket, void *buf, size_t count,
+static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t count,
struct net_ip4_addr node, uint16_t port) {
debugf("udp_conn.sendto()");
ASSERT_SELF(packet_conn, UDP);
@@ -896,7 +834,7 @@ static ssize_t w5500_udp_sendto(implements_net_packet_conn *_socket, void *buf,
}
}
-static void w5500_udp_set_read_deadline(implements_net_packet_conn *_socket, uint64_t ns) {
+static void w5500_udp_set_read_deadline(struct _w5500_socket *socket, uint64_t ns) {
debugf("udp_conn.set_read_deadline(%"PRIu64")", ns);
ASSERT_SELF(packet_conn, UDP);
socket->read_deadline_ns = ns;
@@ -907,7 +845,7 @@ static void w5500_udp_alarm_handler(void *_arg) {
cr_sema_signal_from_intrhandler(&socket->read_sema);
}
-static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf, size_t count,
+static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_t count,
struct net_ip4_addr *ret_node, uint16_t *ret_port) {
debugf("udp_conn.recvfrom()");
ASSERT_SELF(packet_conn, UDP);
@@ -975,7 +913,7 @@ static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf
return len;
}
-static int w5500_udp_close(implements_net_packet_conn *_socket) {
+static int w5500_udp_close(struct _w5500_socket *socket) {
debugf("udp_conn.close()");
ASSERT_SELF(packet_conn, UDP);
diff --git a/libhw/w5500_ll.h b/libhw/w5500_ll.h
index c05a04f..92d9f14 100644
--- a/libhw/w5500_ll.h
+++ b/libhw/w5500_ll.h
@@ -15,7 +15,6 @@
#include <libmisc/assert.h> /* for assert(), static_assert() */
#include <libmisc/endian.h> /* for uint16be_t */
-#include <libmisc/vcall.h> /* for VCALL() */
#include <libhw/generic/net.h> /* for struct net_eth_addr, struct net_ip4_addr */
#include <libhw/generic/spi.h> /* for lo_interface spi */
diff --git a/libhw_generic/include/libhw/generic/net.h b/libhw_generic/include/libhw/generic/net.h
index 0f9872e..c888735 100644
--- a/libhw_generic/include/libhw/generic/net.h
+++ b/libhw_generic/include/libhw/generic/net.h
@@ -1,6 +1,6 @@
/* libhw/generic/net.h - Device-independent network definitions
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -13,6 +13,8 @@
#include <stdint.h> /* for uint{n}_t} */
#include <sys/types.h> /* for ssize_t */
+#include <libobj/obj.h>
+
/* Errnos *********************************************************************/
#define NET_EOTHER 1
@@ -54,97 +56,81 @@ struct net_eth_addr {
/* Streams (e.g. TCP) *********************************************************/
-struct net_stream_listener_vtable;
-struct net_stream_conn_vtable;
-
-typedef struct {
- struct net_stream_listener_vtable *vtable;
-} implements_net_stream_listener;
-
-typedef struct {
- struct net_stream_conn_vtable *vtable;
-} implements_net_stream_conn;
-
-struct net_stream_listener_vtable {
- /**
- * It is invalid to accept() a new connection if an existing
- * connection is still open.
- */
- implements_net_stream_conn *(*accept)(implements_net_stream_listener *self);
-
- /**
- * The net_stream_conn returned from accept() may still be
- * valid after the listener is closed.
- *
- * Return 0 on success, -errno on error.
- */
- int (*close)(implements_net_stream_listener *self);
-};
-
-struct net_stream_conn_vtable {
- /**
- * Return bytes-read on success, 0 on EOF, -errno on error; a
- * short read is *not* an error.
- */
- ssize_t (*read)(implements_net_stream_conn *self,
- void *buf, size_t count);
-
- /**
- * Set a timestamp after which calls to read() will return
- * NET_ETIMEDOUT. The timestamp is in nanoseconds on the
- * system monotonic clock, which is usually (on pico-sdk and
- * on the Linux kernel) nanoseconds-since-boot.
- *
- * A zero value disables the deadline.
- *
- * (2⁶⁴-1 nanoseconds is more than 500 years; there is little
- * risk of this overflowing)
- */
- void (*set_read_deadline)(implements_net_stream_conn *self,
- uint64_t ns_since_boot);
-
- /**
- * Return `count` on success, -errno on error; a short write *is* an
- * error.
- *
- * Writes are *not* guaranteed to be atomic (as this would be
- * expensive to implement), so if you have concurrent writers then you
- * should arrange for a mutex to protect the connection.
- */
- ssize_t (*write)(implements_net_stream_conn *self,
- void *buf, size_t count);
-
- /**
- * Return 0 on success, -errno on error.
- */
- int (*close)(implements_net_stream_conn *self,
- bool rd, bool wr);
-};
+lo_interface net_stream_conn;
+
+#define net_stream_listener_LO_IFACE \
+ /** \
+ * It is invalid to accept() a new connection if an existing \
+ * connection is still open. \
+ */ \
+ LO_FUNC(lo_interface net_stream_conn, accept) \
+ \
+ /** \
+ * The net_stream_conn returned from accept() may still be \
+ * valid after the listener is closed. \
+ * \
+ * Return 0 on success, -errno on error. \
+ */ \
+ LO_FUNC(int, close)
+LO_INTERFACE(net_stream_listener)
+
+#define net_stream_conn_LO_IFACE \
+ /** \
+ * Return bytes-read on success, 0 on EOF, -errno on error; a \
+ * short read is *not* an error. \
+ */ \
+ LO_FUNC(ssize_t, read, void *buf, size_t count) \
+ \
+ /** \
+ * Set a timestamp after which calls to read() will return \
+ * NET_ETIMEDOUT. The timestamp is in nanoseconds on the \
+ * system monotonic clock, which is usually (on pico-sdk and \
+ * on the Linux kernel) nanoseconds-since-boot. \
+ * \
+ * A zero value disables the deadline. \
+ * \
+ * (2⁶⁴-1 nanoseconds is more than 500 years; there is little \
+ * risk of this overflowing) \
+ */ \
+ LO_FUNC(void, set_read_deadline, uint64_t ns_since_boot) \
+ \
+ /** \
+ * Return `count` on success, -errno on error; a short write *is* an \
+ * error. \
+ * \
+ * Writes are *not* guaranteed to be atomic (as this would be \
+ * expensive to implement), so if you have concurrent writers then you \
+ * should arrange for a mutex to protect the connection. \
+ */ \
+ LO_FUNC(ssize_t, write, void *buf, size_t count) \
+ \
+ /** \
+ * Return 0 on success, -errno on error. \
+ */ \
+ LO_FUNC(int, close, bool rd, bool wr)
+LO_INTERFACE(net_stream_conn)
/* Packets (e.g. UDP) *********************************************************/
-struct net_packet_conn_vtable;
-
-typedef struct {
- struct net_packet_conn_vtable *vtable;
-} implements_net_packet_conn;
-
-struct net_packet_conn_vtable {
- ssize_t (*sendto )(implements_net_packet_conn *self,
- void *buf, size_t len,
- struct net_ip4_addr node, uint16_t port);
- /**
- * @return The full length of the message, which may be more
- * than the given `len` (as if the Linux MSG_TRUNC flag were
- * given).
- */
- ssize_t (*recvfrom)(implements_net_packet_conn *self,
- void *buf, size_t len,
- struct net_ip4_addr *ret_node, uint16_t *ret_port);
- void (*set_read_deadline)(implements_net_packet_conn *self,
- uint64_t ns_since_boot);
- int (*close )(implements_net_packet_conn *self);
-};
+#define net_packet_conn_LO_IFACE \
+ LO_FUNC(ssize_t, sendto, \
+ void *buf, size_t len, \
+ struct net_ip4_addr node, uint16_t port) \
+ \
+ /** \
+ * @return The full length of the message, which may be more \
+ * than the given `len` (as if the Linux MSG_TRUNC flag were \
+ * given). \
+ */ \
+ LO_FUNC(ssize_t, recvfrom, \
+ void *buf, size_t len, \
+ struct net_ip4_addr *ret_node, uint16_t *ret_port) \
+ \
+ LO_FUNC(void, set_read_deadline, \
+ uint64_t ns_since_boot) \
+ \
+ LO_FUNC(int, close)
+LO_INTERFACE(net_packet_conn)
/* Interfaces *****************************************************************/
@@ -154,20 +140,14 @@ struct net_iface_config {
struct net_ip4_addr subnet_mask;
};
-struct net_iface_vtable;
-
-typedef struct {
- struct net_iface_vtable *vtable;
-} implements_net_iface;
-
-struct net_iface_vtable {
- struct net_eth_addr (*hwaddr )(implements_net_iface *);
- void (*ifup )(implements_net_iface *, struct net_iface_config);
- void (*ifdown )(implements_net_iface *);
-
- implements_net_stream_listener *(*tcp_listen)(implements_net_iface *, uint16_t local_port);
- implements_net_stream_conn *(*tcp_dial )(implements_net_iface *, struct net_ip4_addr remote_node, uint16_t remote_port);
- implements_net_packet_conn *(*udp_conn )(implements_net_iface *, uint16_t local_port);
-};
+#define net_iface_LO_IFACE \
+ LO_FUNC(struct net_eth_addr , hwaddr ) \
+ LO_FUNC(void , ifup , struct net_iface_config) \
+ LO_FUNC(void , ifdown ) \
+ \
+ LO_FUNC(lo_interface net_stream_listener, tcp_listen, uint16_t local_port) \
+ LO_FUNC(lo_interface net_stream_conn , tcp_dial , struct net_ip4_addr remote_node, uint16_t remote_port) \
+ LO_FUNC(lo_interface net_packet_conn , udp_conn , uint16_t local_port)
+LO_INTERFACE(net_iface)
#endif /* _LIBHW_GENERIC_NET_H_ */