aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarehbein <arehbein@sysmocom.de>2023-04-11 13:30:29 +0200
committerarehbein <arehbein@sysmocom.de>2023-06-19 18:30:47 +0000
commit2c59d1285e8f4c47122e1749ff1ac60e99a1874e (patch)
tree48bf4d5b36f90368fd4f089bf4beb88f39b8a5bb
parent5099d99192e339db017dcae7968e4c6835d4d1ca (diff)
gsm/ipa: Add segmentation callback
Add segmentation callback to be used by the streaming backend of libosmo-netif Related: OS#5753, OS#5751 Change-Id: I3a639e6896cc3b3fc8e9b2e1a58254710efa0d3f
-rw-r--r--include/osmocom/gsm/ipa.h3
-rw-r--r--src/gsm/ipa.c29
-rw-r--r--src/gsm/libosmogsm.map1
3 files changed, 33 insertions, 0 deletions
diff --git a/include/osmocom/gsm/ipa.h b/include/osmocom/gsm/ipa.h
index 851b58e0..8a4dd3ff 100644
--- a/include/osmocom/gsm/ipa.h
+++ b/include/osmocom/gsm/ipa.h
@@ -79,3 +79,6 @@ struct msgb *ipa_msg_alloc(int headroom);
int ipa_msg_recv(int fd, struct msgb **rmsg);
int ipa_msg_recv_buffered(int fd, struct msgb **rmsg, struct msgb **tmp_msg);
+
+/* Callback for segmenting TCP stream data into IPA packets */
+int ipa_segmentation_cb(struct msgb *msg);
diff --git a/src/gsm/ipa.c b/src/gsm/ipa.c
index 447e8e3d..93e34df2 100644
--- a/src/gsm/ipa.c
+++ b/src/gsm/ipa.c
@@ -30,6 +30,7 @@
#include <stdint.h>
#include <errno.h>
#include <stdlib.h>
+#include <inttypes.h>
#include <sys/types.h>
@@ -718,4 +719,32 @@ struct msgb *ipa_msg_alloc(int headroom)
return nmsg;
}
+/*! Segmentation callback used by libosmo-netif streaming backend
+ * See definition of `struct osmo_io_ops` for callback semantics
+ * \param[in] msg Original `struct msgb` received via osmo_io
+ * \returns The total packet length indicated by the first header,
+ * otherwise
+ * -EAGAIN, if the header has not been read yet,
+ * -ENOBUFS, if the header declares a payload too large
+ */
+int ipa_segmentation_cb(struct msgb *msg)
+{
+ const struct ipaccess_head *hh = (const struct ipaccess_head *) msg->data;
+ size_t payload_len, total_len;
+ size_t available = msgb_length(msg) + msgb_tailroom(msg);
+ if (msgb_length(msg) < sizeof(*hh)) {
+ /* Haven't even read the entire header */
+ return -EAGAIN;
+ }
+ payload_len = osmo_ntohs(hh->len);
+ total_len = sizeof(*hh) + payload_len;
+ if (OSMO_UNLIKELY(available < total_len)) {
+ LOGP(DLINP, LOGL_ERROR, "Not enough space left in message buffer. "
+ "Have %zu octets, but need %zu\n",
+ available, total_len);
+ return -ENOBUFS;
+ }
+ return total_len;
+}
+
/*! @} */
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 29bf94fd..1e5a7b20 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -689,6 +689,7 @@ ipa_ccm_id_get_parse;
ipa_ccm_id_resp_parse;
ipa_ccm_make_id_resp;
ipa_ccm_make_id_resp_from_req;
+ipa_segmentation_cb;
ipa_msg_alloc;
ipa_msg_recv;
ipa_msg_recv_buffered;