diff options
Diffstat (limited to 'libhw_generic/include/libhw/generic/net.h')
-rw-r--r-- | libhw_generic/include/libhw/generic/net.h | 196 |
1 files changed, 92 insertions, 104 deletions
diff --git a/libhw_generic/include/libhw/generic/net.h b/libhw_generic/include/libhw/generic/net.h index 150d199..4af574b 100644 --- a/libhw_generic/include/libhw/generic/net.h +++ b/libhw_generic/include/libhw/generic/net.h @@ -1,17 +1,20 @@ /* 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 */ #ifndef _LIBHW_GENERIC_NET_H_ #define _LIBHW_GENERIC_NET_H_ +#include <inttypes.h> /* for PRI{u,x}{n} */ #include <stdbool.h> /* for bool */ #include <stddef.h> /* for size_t */ #include <stdint.h> /* for uint{n}_t} */ #include <sys/types.h> /* for ssize_t */ +#include <libhw/generic/io.h> + /* Errnos *********************************************************************/ #define NET_EOTHER 1 @@ -22,6 +25,8 @@ #define NET_ECLOSED 6 #define NET_EMSGSIZE 7 +const char *net_strerror(int net_errno); + /* Address types **************************************************************/ struct net_ip4_addr { @@ -31,103 +36,92 @@ struct net_ip4_addr { static const struct net_ip4_addr net_ip4_addr_broadcast = {{255, 255, 255, 255}}; static const struct net_ip4_addr net_ip4_addr_zero = {{0, 0, 0, 0}}; +#define PRI_net_ip4_addr "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8 +#define ARG_net_ip4_addr(addr) (addr).octets[0], \ + (addr).octets[1], \ + (addr).octets[2], \ + (addr).octets[3] + struct net_eth_addr { unsigned char octets[6]; }; -/* Streams (e.g. TCP) *********************************************************/ +#define PRI_net_eth_addr "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8 +#define ARG_net_eth_addr(addr) (addr).octets[0], \ + (addr).octets[1], \ + (addr).octets[2], \ + (addr).octets[3], \ + (addr).octets[4], \ + (addr).octets[5] -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); -}; +/* Streams (e.g. TCP) *********************************************************/ -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. \ + */ \ + LO_NEST(io_closer) +LO_INTERFACE(net_stream_listener); + +#define net_stream_conn_LO_IFACE \ + LO_NEST(io_readwriter) \ + LO_NEST(io_bidi_closer) \ + \ + /** \ + * 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) +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) \ + \ + /** \ + * Set a timestamp after which calls to recvfrom() 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_recv_deadline, \ + uint64_t ns_since_boot) \ + \ + LO_NEST(io_closer) +LO_INTERFACE(net_packet_conn); /* Interfaces *****************************************************************/ @@ -137,20 +131,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_ */ |