mirror of https://gerrit.osmocom.org/libosmocore
167 lines
4.8 KiB
C
167 lines
4.8 KiB
C
/*! \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);
|