blob: a4b0749df230c42008fc8da4e25153057d174cfd [file] [log] [blame]
Harald Welte8857f3b2022-11-18 13:54:44 +01001/*! \file osmo_io_internal.h */
2
3#pragma once
4
5#include <unistd.h>
6#include <stdbool.h>
Harald Welte1047ed72023-11-18 18:51:58 +01007#include <netinet/sctp.h>
Harald Welte8857f3b2022-11-18 13:54:44 +01008
9#include <osmocom/core/osmo_io.h>
10#include <osmocom/core/linuxlist.h>
11#include <osmocom/core/msgb.h>
12#include <osmocom/core/select.h>
13#include <osmocom/core/socket.h>
14
15#include "../config.h"
16
17#define OSMO_IO_DEFAULT_MSGB_SIZE 1024
18#define OSMO_IO_DEFAULT_MSGB_HEADROOM 128
19
20extern const struct iofd_backend_ops iofd_poll_ops;
21#define OSMO_IO_BACKEND_DEFAULT "POLL"
22
Daniel Willmannf91d2aa2023-01-04 18:20:55 +010023#if defined(HAVE_URING)
24extern const struct iofd_backend_ops iofd_uring_ops;
25#endif
26
Harald Welte8857f3b2022-11-18 13:54:44 +010027struct iofd_backend_ops {
28 int (*register_fd)(struct osmo_io_fd *iofd);
29 int (*unregister_fd)(struct osmo_io_fd *iofd);
30 int (*close)(struct osmo_io_fd *iofd);
31 void (*write_enable)(struct osmo_io_fd *iofd);
32 void (*write_disable)(struct osmo_io_fd *iofd);
33 void (*read_enable)(struct osmo_io_fd *iofd);
34 void (*read_disable)(struct osmo_io_fd *iofd);
Andreas Eversberg848faf92024-02-09 12:38:17 +010035 void (*notify_connected)(struct osmo_io_fd *iofd);
Harald Welte8857f3b2022-11-18 13:54:44 +010036};
37
Daniel Willmannf89162f2023-06-26 19:24:46 +020038#define IOFD_FLAG_CLOSED (1<<0)
39#define IOFD_FLAG_IN_CALLBACK (1<<1)
40#define IOFD_FLAG_TO_FREE (1<<2)
41#define IOFD_FLAG_NOTIFY_CONNECTED (1<<3)
Andreas Eversberg848faf92024-02-09 12:38:17 +010042#define IOFD_FLAG_FD_REGISTERED (1<<4)
Daniel Willmannf89162f2023-06-26 19:24:46 +020043
44#define IOFD_FLAG_SET(iofd, flag) \
45 (iofd)->flags |= (flag)
46
47#define IOFD_FLAG_UNSET(iofd, flag) \
48 (iofd)->flags &= ~(flag)
49
50#define IOFD_FLAG_ISSET(iofd, flag) ((iofd)->flags & (flag))
51
Harald Welte8857f3b2022-11-18 13:54:44 +010052struct osmo_io_fd {
53 /*! linked list for internal management */
54 struct llist_head list;
55 /*! actual operating-system level file decriptor */
56 int fd;
57 /*! type of read/write mode to use */
58 enum osmo_io_fd_mode mode;
59
60 /*! flags to guard closing/freeing of iofd */
Daniel Willmannf89162f2023-06-26 19:24:46 +020061 uint32_t flags;
Harald Welte8857f3b2022-11-18 13:54:44 +010062
Harald Welte8857f3b2022-11-18 13:54:44 +010063 /*! human-readable name to associte with fd */
Pau Espin Pedrol63e45e62023-06-16 16:19:45 +020064 char *name;
Harald Welte8857f3b2022-11-18 13:54:44 +010065
66 /*! send/recv (msg) callback functions */
67 struct osmo_io_ops io_ops;
68 /*! Pending msgb to keep partial data during segmentation */
69 struct msgb *pending;
70
71 /*! data pointer passed through to call-back function */
72 void *data;
73 /*! private number, extending \a data */
74 unsigned int priv_nr;
75
Harald Welte1047ed72023-11-18 18:51:58 +010076 /*! size of iofd_msghdr.cmsg[] when allocated in recvmsg path */
77 size_t cmsg_size;
78
Harald Welte8857f3b2022-11-18 13:54:44 +010079 struct {
80 /*! talloc context from which to allocate msgb when reading */
81 const void *ctx;
82 /*! size of msgb to allocate (excluding headroom) */
83 unsigned int size;
84 /*! headroom to allocate when allocating msgb's */
85 unsigned int headroom;
86 } msgb_alloc;
87
88 struct {
89 /*! maximum length of write queue */
90 unsigned int max_length;
91 /*! current length of write queue */
92 unsigned int current_length;
93 /*! actual linked list implementing the transmit queue */
94 struct llist_head msg_queue;
95 } tx_queue;
96
97 union {
98 struct {
99 struct osmo_fd ofd;
100 } poll;
101 struct {
102 bool read_enabled;
Harald Welte8857f3b2022-11-18 13:54:44 +0100103 bool write_enabled;
Daniel Willmannf91d2aa2023-01-04 18:20:55 +0100104 void *read_msghdr;
105 void *write_msghdr;
Harald Welte8857f3b2022-11-18 13:54:44 +0100106 /* TODO: index into array of registered fd's? */
Andreas Eversbergd7256c62024-02-09 13:01:15 +0100107 /* osmo_fd for non-blocking connect handling */
108 struct osmo_fd connect_ofd;
Harald Welte8857f3b2022-11-18 13:54:44 +0100109 } uring;
110 } u;
111};
112
113enum iofd_msg_action {
114 IOFD_ACT_READ,
115 IOFD_ACT_WRITE,
116 IOFD_ACT_RECVFROM,
117 IOFD_ACT_SENDTO,
Harald Welte1047ed72023-11-18 18:51:58 +0100118 IOFD_ACT_RECVMSG,
119 IOFD_ACT_SENDMSG,
Harald Welte8857f3b2022-11-18 13:54:44 +0100120};
121
122
Harald Welte987a86a2023-11-18 18:46:24 +0100123/*! serialized version of 'struct msghdr' employed by sendmsg/recvmsg */
Harald Welte8857f3b2022-11-18 13:54:44 +0100124struct iofd_msghdr {
Harald Welte987a86a2023-11-18 18:46:24 +0100125 /*! entry into osmo_io_fd.tx_queue.msg_queue */
Harald Welte8857f3b2022-11-18 13:54:44 +0100126 struct llist_head list;
127 enum iofd_msg_action action;
Harald Welte987a86a2023-11-18 18:46:24 +0100128 /*! the 'struct msghdr' we are wrapping/ecapsulating here */
Harald Welte8857f3b2022-11-18 13:54:44 +0100129 struct msghdr hdr;
Harald Welte987a86a2023-11-18 18:46:24 +0100130 /*! socket address of the remote peer */
Harald Welte8857f3b2022-11-18 13:54:44 +0100131 struct osmo_sockaddr osa;
Harald Welte987a86a2023-11-18 18:46:24 +0100132 /*! io-vector we need to pass as argument to sendmsg/recvmsg; is set up
133 * to point into msg below */
Harald Welte8857f3b2022-11-18 13:54:44 +0100134 struct iovec iov[1];
Harald Welte987a86a2023-11-18 18:46:24 +0100135 /*! flags we pass as argument to sendmsg / recvmsg */
Harald Welte8857f3b2022-11-18 13:54:44 +0100136 int flags;
137
Harald Welte987a86a2023-11-18 18:46:24 +0100138 /*! message-buffer containing data for this I/O operation */
Harald Welte8857f3b2022-11-18 13:54:44 +0100139 struct msgb *msg;
Harald Welte987a86a2023-11-18 18:46:24 +0100140 /*! I/O file descriptor on which we perform this I/O operation */
Harald Welte8857f3b2022-11-18 13:54:44 +0100141 struct osmo_io_fd *iofd;
Harald Welte1047ed72023-11-18 18:51:58 +0100142
143 /*! control message buffer for passing sctp_sndrcvinfo along */
144 char cmsg[0]; /* size is determined by iofd->cmsg_size on recvmsg, and by mcghdr->msg_controllen on sendmsg */
Harald Welte8857f3b2022-11-18 13:54:44 +0100145};
146
147enum iofd_seg_act {
148 IOFD_SEG_ACT_HANDLE_ONE,
149 IOFD_SEG_ACT_HANDLE_MORE,
150 IOFD_SEG_ACT_DEFER,
151};
152
Harald Welte1047ed72023-11-18 18:51:58 +0100153struct iofd_msghdr *iofd_msghdr_alloc(struct osmo_io_fd *iofd, enum iofd_msg_action action, struct msgb *msg, size_t cmsg_size);
Harald Welte8857f3b2022-11-18 13:54:44 +0100154void iofd_msghdr_free(struct iofd_msghdr *msghdr);
155
156struct msgb *iofd_msgb_alloc(struct osmo_io_fd *iofd);
157struct msgb *iofd_msgb_pending(struct osmo_io_fd *iofd);
158struct msgb *iofd_msgb_pending_or_alloc(struct osmo_io_fd *iofd);
159
Daniel Willmann2b34e922023-08-23 18:02:13 +0200160void iofd_handle_recv(struct osmo_io_fd *iofd, struct msgb *msg, int rc, struct iofd_msghdr *msghdr);
Daniel Willmann84611882023-11-21 10:17:00 +0100161void iofd_handle_send_completion(struct osmo_io_fd *iofd, int rc, struct iofd_msghdr *msghdr);
Harald Welte8857f3b2022-11-18 13:54:44 +0100162void iofd_handle_segmented_read(struct osmo_io_fd *iofd, struct msgb *msg, int rc);
163
164int iofd_txqueue_enqueue(struct osmo_io_fd *iofd, struct iofd_msghdr *msghdr);
165void iofd_txqueue_enqueue_front(struct osmo_io_fd *iofd, struct iofd_msghdr *msghdr);
166struct iofd_msghdr *iofd_txqueue_dequeue(struct osmo_io_fd *iofd);