From 99750d5cae843e01180bc0baeafc06da78d1b0b7 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Wed, 17 Apr 2024 14:11:43 +0200 Subject: osmo_io: Add iofd param to segmentation_cb See related ticket for full rant and historical facts about this callback. Since anyway we are still developing osmo_io stuff and there will be ABI breaks when releasing new version, let's udpate the callback signature too. Related: OS#6437 Change-Id: Ib8d77e30b1ea759ee5ac2a69d704e81ea71e3079 --- include/osmocom/core/osmo_io.h | 32 ++++++++++++++++++++++++++++---- src/core/osmo_io.c | 12 +++++++++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/include/osmocom/core/osmo_io.h b/include/osmocom/core/osmo_io.h index 8c931ddd..6f4dfa8a 100644 --- a/include/osmocom/core/osmo_io.h +++ b/include/osmocom/core/osmo_io.h @@ -100,6 +100,7 @@ struct osmo_io_ops { * \param[in] msg message buffer containing the read data. Ownership is transferred to the * call-back, and it must make sure to msgb_free() it eventually! */ void (*read_cb)(struct osmo_io_fd *iofd, int res, struct msgb *msg); + /*! completion call-back function when write issued via osmo_iofd_write_msgb() has completed * on fd. Only valid in OSMO_IO_FD_MODE_READ_WRITE. * \param[in] iofd on which a write() has completed. @@ -108,9 +109,14 @@ struct osmo_io_ops { * call-back; it is automatically freed after the call-back terminates! */ void (*write_cb)(struct osmo_io_fd *iofd, int res, struct msgb *msg); - /*! optional call-back function to segment the data at message boundaries. This is useful when - * message boundaries are to be preserved over a SOCK_STREAM transport socket like TCP. Can - * be NULL for any application not requiring de-segmentation of received data. + + /*! optional call-back function to segment the data at message boundaries. + * \param[in] msg message buffer whose data is to be segmented + * \returns See full function description. + * + * This is useful when message boundaries are to be preserved over a SOCK_STREAM transport + * socket like TCP. Can be NULL for any application not requiring de-segmentation of + * received data. * * The call-back needs to return the size of the next message. If it returns * -EAGAIN or a value larger than msgb_length() (message is incomplete) @@ -119,8 +125,26 @@ struct osmo_io_ops { * If a full message was received (segmentation_cb() returns a value <= msgb_length()) * the msgb will be trimmed to size by osmo_io and forwarded to the read call-back. Any * parsing done to the msgb by segmentation_cb() will be preserved for the read_cb() - * (e.g. setting lxh or msgb->cb). */ + * (e.g. setting lxh or msgb->cb). + * + * Only one (or none) of both segmentation_cb and segmentation_cb2 shall be set. + * Having both set will be considered an error during iofd setup. */ int (*segmentation_cb)(struct msgb *msg); + + /*! optional call-back function to segment the data at message boundaries. + * \param[in] iofd handling msg + * \param[in] msg message buffer whose data is to be segmented + * \returns See full function description. + * + * Same as segmentation_cb above, with an extra parameter to have access to the iofd and its + * related functionalities (eg data pointer). This is useful for users requiring to store + * global state or access external objects while segmenting. + * + * The provided iofd shall not be freed by the user during the callback. + * + * Only one (or none) of both segmentation_cb and segmentation_cb2 shall be set. + * Having both set will be considered an error during iofd setup. */ + int (*segmentation_cb2)(struct osmo_io_fd *iofd, struct msgb *msg); }; /* mode OSMO_IO_FD_MODE_RECVFROM_SENDTO: */ diff --git a/src/core/osmo_io.c b/src/core/osmo_io.c index b589cb71..af096e6e 100644 --- a/src/core/osmo_io.c +++ b/src/core/osmo_io.c @@ -267,7 +267,7 @@ struct iofd_msghdr *iofd_txqueue_dequeue(struct osmo_io_fd *iofd) */ static enum iofd_seg_act iofd_handle_segmentation(struct osmo_io_fd *iofd, struct msgb *msg, struct msgb **pending_out) { - int extra_len, received_len; + int extra_len, received_len, expected_len; struct msgb *msg_pending; /* Save the start of message before segmentation_cb (which could change it) */ @@ -275,12 +275,15 @@ static enum iofd_seg_act iofd_handle_segmentation(struct osmo_io_fd *iofd, struc received_len = msgb_length(msg); - if (!iofd->io_ops.segmentation_cb) { + if (iofd->io_ops.segmentation_cb2) { + expected_len = iofd->io_ops.segmentation_cb2(iofd, msg); + } else if (iofd->io_ops.segmentation_cb) { + expected_len = iofd->io_ops.segmentation_cb(msg); + } else { *pending_out = NULL; return IOFD_SEG_ACT_HANDLE_ONE; } - int expected_len = iofd->io_ops.segmentation_cb(msg); if (expected_len == -EAGAIN) { goto defer; } else if (expected_len < 0) { @@ -599,6 +602,9 @@ static int check_mode_callback_compat(enum osmo_io_fd_mode mode, const struct os return false; if (ops->recvmsg_cb || ops->sendmsg_cb) return false; + /* Forbid both segementation_cb set, something is wrong: */ + if (ops->segmentation_cb && ops->segmentation_cb2) + return false; break; case OSMO_IO_FD_MODE_RECVFROM_SENDTO: if (ops->read_cb || ops->write_cb) -- cgit v1.2.3