laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/33685 )
Change subject: osmo_io: Document expectation that segmentation_cb() can modify msgb ......................................................................
osmo_io: Document expectation that segmentation_cb() can modify msgb
This is used for parsing e.g. the ipa header and setting msg->cb. Guard against segmentation_cb changing msg->data in iofd_handle_segmentation().
Change-Id: Idd2115baae98a7818aabb26232d4423d2d48fb5c --- M include/osmocom/core/osmo_io.h M src/core/osmo_io.c 2 files changed, 26 insertions(+), 4 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved Jenkins Builder: Verified
diff --git a/include/osmocom/core/osmo_io.h b/include/osmocom/core/osmo_io.h index 932b909..3715f93 100644 --- a/include/osmocom/core/osmo_io.h +++ b/include/osmocom/core/osmo_io.h @@ -46,7 +46,11 @@ * Needs to return the size of the next message. If it returns * -EAGAIN or a value larger than msgb_length() (message is incomplete) * osmo_io will wait for more data to be read. Other negative values - * cause the msg to be discarded. */ + * cause the msg to be discarded. + * 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). */ int (*segmentation_cb)(struct msgb *msg); };
diff --git a/src/core/osmo_io.c b/src/core/osmo_io.c index fdb9e32..8217316 100644 --- a/src/core/osmo_io.c +++ b/src/core/osmo_io.c @@ -226,6 +226,9 @@ int extra_len, received_len; struct msgb *msg_pending;
+ /* Save the start of message before segmentation_cb (which could change it) */ + uint8_t *data = msg->data; + received_len = msgb_length(msg);
if (!iofd->io_ops.segmentation_cb) { @@ -258,12 +261,14 @@ /* msgb contains more than one segment */ /* Copy the trailing data over */ msg_pending = iofd_msgb_alloc(iofd); - memcpy(msgb_data(msg_pending), msgb_data(msg) + expected_len, extra_len); + memcpy(msgb_data(msg_pending), data + expected_len, extra_len); msgb_put(msg_pending, extra_len); *pending_out = msg_pending;
- /* Trim the original msgb to size */ - msgb_trim(msg, expected_len); + /* Trim the original msgb to size. Don't use msgb_trim because we need to reference + * msg->data from before it might have been modified by the segmentation_cb(). */ + msg->len = expected_len; + msg->tail = data + expected_len; return IOFD_SEG_ACT_HANDLE_MORE;
defer: