Add osmo_io with initial poll backend

* make backend configurable for later
* segmentation callback for chunked streams
* logging target for osmo_io
* support partial writes

Change-Id: I50d73cf550d6ce8154bf827bf47408131cf5b0a0
Related: SYS#5094, OS#5751
diff --git a/include/osmocom/core/osmo_io.h b/include/osmocom/core/osmo_io.h
new file mode 100644
index 0000000..ffc8cfa
--- /dev/null
+++ b/include/osmocom/core/osmo_io.h
@@ -0,0 +1,90 @@
+/*! \file osmo_io.h
+ *  io(_uring) abstraction osmo fd compatibility
+ */
+
+#pragma once
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/socket.h>
+#include <osmocom/core/utils.h>
+
+
+#define LOGPIO(iofd, level, fmt, args...) \
+	LOGP(DLIO, level, "iofd(%s)" fmt, iofd->name, ## args)
+
+struct osmo_io_fd;
+
+enum osmo_io_fd_mode {
+	/*! use read() / write() calls */
+	OSMO_IO_FD_MODE_READ_WRITE,
+	/*! use recvfrom() / sendto() calls */
+	OSMO_IO_FD_MODE_RECVFROM_SENDTO,
+	/*! emulate sctp_recvmsg() and sctp_sendmsg() */
+	OSMO_IO_FD_MODE_SCTP_RECVMSG_SENDMSG,
+};
+
+enum osmo_io_backend {
+	OSMO_IO_BACKEND_POLL,
+};
+
+extern const struct value_string osmo_io_backend_names[];
+static inline const char *osmo_io_backend_name(enum osmo_io_backend val)
+{ return get_value_string(osmo_io_backend_names, val); }
+
+struct osmo_io_ops {
+	union {
+		/* mode OSMO_IO_FD_MODE_READ_WRITE: */
+		struct {
+			/*! call-back function when something was read from fd */
+			void (*read_cb)(struct osmo_io_fd *iofd, int res, struct msgb *msg);
+			/*! call-back function when write has completed on fd */
+			void (*write_cb)(struct osmo_io_fd *iofd, int res,
+					 const struct msgb *msg);
+			/*! call-back function to segment the data returned by read_cb */
+			int (*segmentation_cb)(struct msgb *msg, int data_len);
+		};
+
+		/* mode OSMO_IO_FD_MODE_RECVFROM_SENDTO: */
+		struct {
+			/*! call-back function emulating sendto */
+			void (*sendto_cb)(struct osmo_io_fd *iofd, int res,
+					  const struct msgb *msg,
+					  const struct osmo_sockaddr *daddr);
+			/*! call-back function emulating recvfrom */
+			void (*recvfrom_cb)(struct osmo_io_fd *iofd, int res,
+					    struct msgb *msg,
+					    const struct osmo_sockaddr *saddr);
+		};
+	};
+};
+
+void osmo_io_init(void);
+
+struct osmo_io_fd *osmo_iofd_setup(const void *ctx, int fd, const char *name,
+		  enum osmo_io_fd_mode mode, const struct osmo_io_ops *ioops, void *data);
+int osmo_iofd_register(struct osmo_io_fd *iofd, int fd);
+int osmo_iofd_unregister(struct osmo_io_fd *iofd);
+unsigned int osmo_iofd_txqueue_len(struct osmo_io_fd *iofd);
+void osmo_iofd_txqueue_clear(struct osmo_io_fd *iofd);
+int osmo_iofd_close(struct osmo_io_fd *iofd);
+void osmo_iofd_free(struct osmo_io_fd *iofd);
+void osmo_iofd_read_enable(struct osmo_io_fd *iofd);
+void osmo_iofd_read_disable(struct osmo_io_fd *iofd);
+void osmo_iofd_write_enable(struct osmo_io_fd *iofd);
+void osmo_iofd_write_disable(struct osmo_io_fd *iofd);
+
+int osmo_iofd_write_msgb(struct osmo_io_fd *iofd, struct msgb *msg);
+int osmo_iofd_sendto_msgb(struct osmo_io_fd *iofd, struct msgb *msg, int sendto_flags,
+			  const struct osmo_sockaddr *dest);
+
+void osmo_iofd_set_alloc_info(struct osmo_io_fd *iofd, unsigned int size, unsigned int headroom);
+void *osmo_iofd_get_data(const struct osmo_io_fd *iofd);
+void osmo_iofd_set_data(struct osmo_io_fd *iofd, void *data);
+
+unsigned int osmo_iofd_get_priv_nr(const struct osmo_io_fd *iofd);
+void osmo_iofd_set_priv_nr(struct osmo_io_fd *iofd, unsigned int priv_nr);
+
+int osmo_iofd_get_fd(const struct osmo_io_fd *iofd);
+const char *osmo_iofd_get_name(const struct osmo_io_fd *iofd);