diff options
Diffstat (limited to 'src/core/osmo_io_internal.h')
-rw-r--r-- | src/core/osmo_io_internal.h | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/core/osmo_io_internal.h b/src/core/osmo_io_internal.h new file mode 100644 index 00000000..a4b0749d --- /dev/null +++ b/src/core/osmo_io_internal.h @@ -0,0 +1,166 @@ +/*! \file osmo_io_internal.h */ + +#pragma once + +#include <unistd.h> +#include <stdbool.h> +#include <netinet/sctp.h> + +#include <osmocom/core/osmo_io.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/select.h> +#include <osmocom/core/socket.h> + +#include "../config.h" + +#define OSMO_IO_DEFAULT_MSGB_SIZE 1024 +#define OSMO_IO_DEFAULT_MSGB_HEADROOM 128 + +extern const struct iofd_backend_ops iofd_poll_ops; +#define OSMO_IO_BACKEND_DEFAULT "POLL" + +#if defined(HAVE_URING) +extern const struct iofd_backend_ops iofd_uring_ops; +#endif + +struct iofd_backend_ops { + int (*register_fd)(struct osmo_io_fd *iofd); + int (*unregister_fd)(struct osmo_io_fd *iofd); + int (*close)(struct osmo_io_fd *iofd); + void (*write_enable)(struct osmo_io_fd *iofd); + void (*write_disable)(struct osmo_io_fd *iofd); + void (*read_enable)(struct osmo_io_fd *iofd); + void (*read_disable)(struct osmo_io_fd *iofd); + void (*notify_connected)(struct osmo_io_fd *iofd); +}; + +#define IOFD_FLAG_CLOSED (1<<0) +#define IOFD_FLAG_IN_CALLBACK (1<<1) +#define IOFD_FLAG_TO_FREE (1<<2) +#define IOFD_FLAG_NOTIFY_CONNECTED (1<<3) +#define IOFD_FLAG_FD_REGISTERED (1<<4) + +#define IOFD_FLAG_SET(iofd, flag) \ + (iofd)->flags |= (flag) + +#define IOFD_FLAG_UNSET(iofd, flag) \ + (iofd)->flags &= ~(flag) + +#define IOFD_FLAG_ISSET(iofd, flag) ((iofd)->flags & (flag)) + +struct osmo_io_fd { + /*! linked list for internal management */ + struct llist_head list; + /*! actual operating-system level file decriptor */ + int fd; + /*! type of read/write mode to use */ + enum osmo_io_fd_mode mode; + + /*! flags to guard closing/freeing of iofd */ + uint32_t flags; + + /*! human-readable name to associte with fd */ + char *name; + + /*! send/recv (msg) callback functions */ + struct osmo_io_ops io_ops; + /*! Pending msgb to keep partial data during segmentation */ + struct msgb *pending; + + /*! data pointer passed through to call-back function */ + void *data; + /*! private number, extending \a data */ + unsigned int priv_nr; + + /*! size of iofd_msghdr.cmsg[] when allocated in recvmsg path */ + size_t cmsg_size; + + struct { + /*! talloc context from which to allocate msgb when reading */ + const void *ctx; + /*! size of msgb to allocate (excluding headroom) */ + unsigned int size; + /*! headroom to allocate when allocating msgb's */ + unsigned int headroom; + } msgb_alloc; + + struct { + /*! maximum length of write queue */ + unsigned int max_length; + /*! current length of write queue */ + unsigned int current_length; + /*! actual linked list implementing the transmit queue */ + struct llist_head msg_queue; + } tx_queue; + + union { + struct { + struct osmo_fd ofd; + } poll; + struct { + bool read_enabled; + bool write_enabled; + void *read_msghdr; + void *write_msghdr; + /* TODO: index into array of registered fd's? */ + /* osmo_fd for non-blocking connect handling */ + struct osmo_fd connect_ofd; + } uring; + } u; +}; + +enum iofd_msg_action { + IOFD_ACT_READ, + IOFD_ACT_WRITE, + IOFD_ACT_RECVFROM, + IOFD_ACT_SENDTO, + IOFD_ACT_RECVMSG, + IOFD_ACT_SENDMSG, +}; + + +/*! serialized version of 'struct msghdr' employed by sendmsg/recvmsg */ +struct iofd_msghdr { + /*! entry into osmo_io_fd.tx_queue.msg_queue */ + struct llist_head list; + enum iofd_msg_action action; + /*! the 'struct msghdr' we are wrapping/ecapsulating here */ + struct msghdr hdr; + /*! socket address of the remote peer */ + struct osmo_sockaddr osa; + /*! io-vector we need to pass as argument to sendmsg/recvmsg; is set up + * to point into msg below */ + struct iovec iov[1]; + /*! flags we pass as argument to sendmsg / recvmsg */ + int flags; + + /*! message-buffer containing data for this I/O operation */ + struct msgb *msg; + /*! I/O file descriptor on which we perform this I/O operation */ + struct osmo_io_fd *iofd; + + /*! control message buffer for passing sctp_sndrcvinfo along */ + char cmsg[0]; /* size is determined by iofd->cmsg_size on recvmsg, and by mcghdr->msg_controllen on sendmsg */ +}; + +enum iofd_seg_act { + IOFD_SEG_ACT_HANDLE_ONE, + IOFD_SEG_ACT_HANDLE_MORE, + IOFD_SEG_ACT_DEFER, +}; + +struct iofd_msghdr *iofd_msghdr_alloc(struct osmo_io_fd *iofd, enum iofd_msg_action action, struct msgb *msg, size_t cmsg_size); +void iofd_msghdr_free(struct iofd_msghdr *msghdr); + +struct msgb *iofd_msgb_alloc(struct osmo_io_fd *iofd); +struct msgb *iofd_msgb_pending(struct osmo_io_fd *iofd); +struct msgb *iofd_msgb_pending_or_alloc(struct osmo_io_fd *iofd); + +void iofd_handle_recv(struct osmo_io_fd *iofd, struct msgb *msg, int rc, struct iofd_msghdr *msghdr); +void iofd_handle_send_completion(struct osmo_io_fd *iofd, int rc, struct iofd_msghdr *msghdr); +void iofd_handle_segmented_read(struct osmo_io_fd *iofd, struct msgb *msg, int rc); + +int iofd_txqueue_enqueue(struct osmo_io_fd *iofd, struct iofd_msghdr *msghdr); +void iofd_txqueue_enqueue_front(struct osmo_io_fd *iofd, struct iofd_msghdr *msghdr); +struct iofd_msghdr *iofd_txqueue_dequeue(struct osmo_io_fd *iofd); |