diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-11-15 11:58:59 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-11-19 20:15:16 -0700 |
commit | 936fd0145896acbf55de496f036af55a01b80e82 (patch) | |
tree | a81cfff1fe552a184d614e7a0639583f0a8f8252 /libhw_generic/include/libhw/generic/net.h | |
parent | 573b0f7d4d4a7e84ae8d1e4a7c0611dd9f513fa2 (diff) |
libhw_generic: Split into a separate library
Diffstat (limited to 'libhw_generic/include/libhw/generic/net.h')
-rw-r--r-- | libhw_generic/include/libhw/generic/net.h | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/libhw_generic/include/libhw/generic/net.h b/libhw_generic/include/libhw/generic/net.h new file mode 100644 index 0000000..def533c --- /dev/null +++ b/libhw_generic/include/libhw/generic/net.h @@ -0,0 +1,154 @@ +/* libhw/generic/net.h - Device-independent network definitions + * + * Copyright (C) 2024 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 <stdbool.h> /* for bool */ +#include <stddef.h> /* for size_t */ +#include <stdint.h> /* for uint{n}_t} */ +#include <sys/types.h> /* for ssize_t */ + +/* Errnos *********************************************************************/ + +#define NET_EOTHER 1 +#define NET_ETIMEDOUT 2 +#define NET_ETHREAD 3 +#define NET_ECLOSED 4 +#define NET_EMSGSIZE 5 + +/* Address types **************************************************************/ + +struct net_ip4_addr { + unsigned char octets[4]; +}; + +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}}; + +struct net_eth_addr { + unsigned char octets[6]; +}; + +/* 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); +}; + +/* 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); +}; + +/* Interfaces *****************************************************************/ + +struct net_iface_config { + struct net_ip4_addr addr; + struct net_ip4_addr gateway_addr; + 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); +}; + +#endif /* _LIBHW_GENERIC_NET_H_ */ |