<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmo-netif/+/26426">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Introduce osmo_prim_srv APIs<br><br>This new module allows easy exchange of osmo_prim based data types over<br>IPC communication (UD socket supported only so far), by replacing the<br>osmo_prim_hdr struct with a serialized header when submitting/receiving<br>it from the IPC socket.<br><br>This patch introduces the server side of the UD socket, but the client<br>side can easily be introduced in the same file whenever needed.<br><br>Related: SYS#5516<br>Change-Id: I7cab15ac092e45a256c4f0bab11b3962df861044<br>---<br>M TODO-RELEASE<br>M include/osmocom/netif/Makefile.am<br>A include/osmocom/netif/prim.h<br>M src/Makefile.am<br>A src/prim.c<br>5 files changed, 432 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmo-netif refs/changes/26/26426/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/TODO-RELEASE b/TODO-RELEASE</span><br><span>index 1c9a2a6..b146231 100644</span><br><span>--- a/TODO-RELEASE</span><br><span>+++ b/TODO-RELEASE</span><br><span>@@ -8,3 +8,4 @@</span><br><span> # If any interfaces have been removed or changed since the last public release: c:r:0.</span><br><span> #library what description / commit summary line</span><br><span> sctp.h new APIs</span><br><span style="color: hsl(120, 100%, 40%);">+prim.h new data type, APIs</span><br><span>diff --git a/include/osmocom/netif/Makefile.am b/include/osmocom/netif/Makefile.am</span><br><span>index d9d030b..92712a9 100644</span><br><span>--- a/include/osmocom/netif/Makefile.am</span><br><span>+++ b/include/osmocom/netif/Makefile.am</span><br><span>@@ -4,6 +4,7 @@</span><br><span> osmux.h \</span><br><span> ipa.h \</span><br><span> ipa_unit.h \</span><br><span style="color: hsl(120, 100%, 40%);">+ prim.h \</span><br><span> rs232.h \</span><br><span> rtp.h \</span><br><span> stream.h</span><br><span>diff --git a/include/osmocom/netif/prim.h b/include/osmocom/netif/prim.h</span><br><span>new file mode 100644</span><br><span>index 0000000..eb2cd9e</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/netif/prim.h</span><br><span>@@ -0,0 +1,46 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Pau Espin Pedrol <pespin@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 3 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU Affero General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU Affero General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program. If not, see <http://www.gnu.org/lienses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/prim.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/select.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/linuxlist.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_prim_srv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Must return -EBADF if the srv struct is destroyed during call. oph and</span><br><span style="color: hsl(120, 100%, 40%);">+ * related msgb is owned by srv and wll be freed after the callback returns. */</span><br><span style="color: hsl(120, 100%, 40%);">+typedef int (*osmo_prim_srv_rx_cb)(struct osmo_prim_srv *srv, struct osmo_prim_hdr *oph);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_prim_hdr *osmo_prim_pkt_alloc(unsigned int sap, unsigned int primitive,</span><br><span style="color: hsl(120, 100%, 40%);">+ enum osmo_prim_operation operation, size_t alloc_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_prim_srv *osmo_prim_srv_alloc(void *ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_prim_srv_free(struct osmo_prim_srv *srv);</span><br><span style="color: hsl(120, 100%, 40%);">+bool osmo_prim_srv_connected(const struct osmo_prim_srv *srv);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_prim_srv_set_addr(struct osmo_prim_srv *srv, const char *path);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_prim_srv_get_addr(struct osmo_prim_srv *srv);</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_prim_srv_set_priv(struct osmo_prim_srv *srv, void *priv);</span><br><span style="color: hsl(120, 100%, 40%);">+void *osmo_prim_srv_get_priv(const struct osmo_prim_srv *srv);</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_prim_srv_set_log_category(struct osmo_prim_srv *srv, int log_cat);</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_prim_srv_set_rx_cb(struct osmo_prim_srv *srv, osmo_prim_srv_rx_cb rx_cb);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_prim_srv_open(struct osmo_prim_srv *srv);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_prim_srv_send(struct osmo_prim_srv *srv, struct msgb *msg);</span><br><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index 438b58e..5c23896 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -17,6 +17,7 @@</span><br><span> ipa_unit.c \</span><br><span> jibuf.c \</span><br><span> osmux.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ prim.c \</span><br><span> rs232.c \</span><br><span> rtp.c \</span><br><span> stream.c</span><br><span>diff --git a/src/prim.c b/src/prim.c</span><br><span>new file mode 100644</span><br><span>index 0000000..050fe90</span><br><span>--- /dev/null</span><br><span>+++ b/src/prim.c</span><br><span>@@ -0,0 +1,383 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/socket.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/un.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/select.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/socket.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/netif/prim.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_prim_pkt_hdr {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t sap; /*!< Service Access Point Identifier */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t primitive; /*!< Primitive number */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t operation; /*! Primitive Operation (enum osmo_prim_operation) */</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__ ((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Here we take advantage of the fact that sizeof(struct</span><br><span style="color: hsl(120, 100%, 40%);">+ * osmo_prim_pkt_hdr) <= sizeof(struct osmo_prim_hdr), so we don't need</span><br><span style="color: hsl(120, 100%, 40%);">+ * to allocate headroom when serializing later.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_static_assert(sizeof(struct osmo_prim_pkt_hdr) <= sizeof(struct osmo_prim_hdr),</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_prim_pkt_alloc_validate_headroom);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Allocate a primitive of given type and its associated msgb.</span><br><span style="color: hsl(120, 100%, 40%);">+* \param[in] sap Service Access Point</span><br><span style="color: hsl(120, 100%, 40%);">+* \param[in] primitive Primitive Number</span><br><span style="color: hsl(120, 100%, 40%);">+* \param[in] operation Primitive Operation (REQ/RESP/IND/CONF)</span><br><span style="color: hsl(120, 100%, 40%);">+* \param[in] alloc_len Total length (including struct osmo_prim_hdr) to allocate for the primitive</span><br><span style="color: hsl(120, 100%, 40%);">+* \returns Pointer to allocated prim_hdr inisde its own msgb. The osmo_prim_hdr</span><br><span style="color: hsl(120, 100%, 40%);">+* is pre-alocated & pre-filled.</span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_prim_hdr *osmo_prim_pkt_alloc(unsigned int sap, unsigned int primitive,</span><br><span style="color: hsl(120, 100%, 40%);">+ enum osmo_prim_operation operation, size_t alloc_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_prim_hdr *oph;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (alloc_len < sizeof(*oph))</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = msgb_alloc(alloc_len, "osmo_prim_pkt_alloc");</span><br><span style="color: hsl(120, 100%, 40%);">+ oph = (struct osmo_prim_hdr *)msgb_put(msg, sizeof(*oph));</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_prim_init(oph, sap, primitive, operation, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->l2h = msg->tail;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return oph;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/******************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * osmo_prim_srv</span><br><span style="color: hsl(120, 100%, 40%);">+ ******************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_prim_srv {</span><br><span style="color: hsl(120, 100%, 40%);">+ void *priv;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *addr;</span><br><span style="color: hsl(120, 100%, 40%);">+ int log_cat; /* Defaults to DLGLOBAL */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd listen_bfd; /* fd for listen socket */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd conn_bfd; /* fd for connection to lcr */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head upqueue; /* queue for sending messages */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_prim_srv_rx_cb rx_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define LOGSRV(srv, lvl, fmt, args...) LOGP((srv)->log_cat, lvl, fmt, ## args)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void _osmo_prim_srv_close(struct osmo_prim_srv *srv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd *bfd = &srv->conn_bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ close(bfd->fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ bfd->fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_unregister(bfd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* re-enable the generation of ACCEPT for new connections */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_read_enable(&srv->listen_bfd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* flush the queue */</span><br><span style="color: hsl(120, 100%, 40%);">+ while (!llist_empty(&srv->upqueue)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = msgb_dequeue(&srv->upqueue);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int _osmo_prim_srv_read(struct osmo_fd *bfd)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_prim_srv *srv = (struct osmo_prim_srv *)bfd->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_prim_pkt_hdr *pkth;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_prim_hdr oph;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = msgb_alloc(1600, "osmo_prim_srv_rx");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!msg)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = recv(bfd->fd, msg->tail, msgb_tailroom(msg), 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ goto close;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (errno == EAGAIN) {</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ goto close;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < sizeof(struct osmo_prim_pkt_hdr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_ERROR, "Received %d bytes on UD Socket, but primitive hdr size "</span><br><span style="color: hsl(120, 100%, 40%);">+ "is %zu, discarding\n", rc, sizeof(struct osmo_prim_pkt_hdr));</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ pkth = (struct osmo_prim_pkt_hdr *)msgb_put(msg, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* De-serialize message: */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_prim_init(&oph, pkth->sap, pkth->primitive, pkth->operation, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_pull(msg, sizeof(*pkth));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (srv->rx_cb)</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = srv->rx_cb(srv, &oph);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* as we always synchronously process the message in _osmo_prim_srv_rx() and</span><br><span style="color: hsl(120, 100%, 40%);">+ * its callbacks, we can free the message here. */</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+close:</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ _osmo_prim_srv_close(srv);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int _osmo_prim_srv_write(struct osmo_fd *bfd)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_prim_srv *srv = bfd->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (!llist_empty(&srv->upqueue)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg, *msg2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* peek at the beginning of the queue */</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = llist_entry(srv->upqueue.next, struct msgb, list);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_write_disable(bfd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!msgb_length(msg)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_ERROR, "message with ZERO "</span><br><span style="color: hsl(120, 100%, 40%);">+ "bytes!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto dontsend;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* try to send it over the socket */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = write(bfd->fd, msgb_data(msg), msgb_length(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ goto close;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (errno == EAGAIN) {</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_write_enable(bfd);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ goto close;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dontsend:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* _after_ we send it, we can deueue */</span><br><span style="color: hsl(120, 100%, 40%);">+ msg2 = msgb_dequeue(&srv->upqueue);</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(msg == msg2);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+close:</span><br><span style="color: hsl(120, 100%, 40%);">+ _osmo_prim_srv_close(srv);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int _osmo_prim_srv_bfd_cb(struct osmo_fd *bfd, unsigned int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (flags & OSMO_FD_READ)</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = _osmo_prim_srv_read(bfd);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc == -EBADF) /* socket is gone, return and don't access it */</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (flags & OSMO_FD_WRITE)</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = _osmo_prim_srv_write(bfd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* accept connection coming from PCU */</span><br><span style="color: hsl(120, 100%, 40%);">+static int _osmo_prim_srv_accept(struct osmo_fd *bfd, unsigned int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_prim_srv *srv = (struct osmo_prim_srv *)bfd->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd *conn_bfd = &srv->conn_bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct sockaddr_un un_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+ socklen_t len;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ len = sizeof(un_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = accept(bfd->fd, (struct sockaddr *) &un_addr, &len);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_ERROR, "Failed to accept a new connection\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (conn_bfd->fd >= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_NOTICE, "UD Socket connects but we already have "</span><br><span style="color: hsl(120, 100%, 40%);">+ "another active connection ?!?\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We already have one LLSK connected, this is all we support */</span><br><span style="color: hsl(120, 100%, 40%);">+ srv->listen_bfd.when &= ~OSMO_FD_READ;</span><br><span style="color: hsl(120, 100%, 40%);">+ close(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_setup(conn_bfd, rc, OSMO_FD_READ, _osmo_prim_srv_bfd_cb, srv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (osmo_fd_register(conn_bfd) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_ERROR, "Failed to register new connection fd\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ close(conn_bfd->fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ conn_bfd->fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_NOTICE, "UD socket connected\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_prim_srv *osmo_prim_srv_alloc(void *ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_prim_srv *srv;</span><br><span style="color: hsl(120, 100%, 40%);">+ srv = talloc_zero(ctx, struct osmo_prim_srv);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!srv)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ srv->log_cat = DLGLOBAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&srv->upqueue);</span><br><span style="color: hsl(120, 100%, 40%);">+ srv->conn_bfd.fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ srv->listen_bfd.fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ return srv;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_prim_srv_free(struct osmo_prim_srv *srv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd *bfd, *conn_bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!srv)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ conn_bfd = &srv->conn_bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (conn_bfd->fd > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ _osmo_prim_srv_close(srv);</span><br><span style="color: hsl(120, 100%, 40%);">+ bfd = &srv->listen_bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+ close(bfd->fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_unregister(bfd);</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(srv);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool osmo_prim_srv_connected(const struct osmo_prim_srv *srv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!srv)</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (srv->conn_bfd.fd <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_prim_srv_set_addr(struct osmo_prim_srv *srv, const char *path)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_talloc_replace_string(srv, &srv->addr, path);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_prim_srv_get_addr(struct osmo_prim_srv *srv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return srv->addr;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_prim_srv_set_priv(struct osmo_prim_srv *srv, void *priv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ srv->priv = priv;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void *osmo_prim_srv_get_priv(const struct osmo_prim_srv *srv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return srv->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_prim_srv_set_log_category(struct osmo_prim_srv *srv, int log_cat)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ srv->log_cat = log_cat;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_prim_srv_set_rx_cb(struct osmo_prim_srv *srv, osmo_prim_srv_rx_cb rx_cb)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ srv->rx_cb = rx_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_prim_srv_open(struct osmo_prim_srv *srv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd *bfd = &srv->listen_bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!srv->addr) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_ERROR, "Cannot open, Address not configured\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = osmo_sock_unix_init(SOCK_SEQPACKET, 0, srv->addr, OSMO_SOCK_F_BIND);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_ERROR, "Could not create %s unix socket: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ srv->addr, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_setup(bfd, rc, OSMO_FD_READ, _osmo_prim_srv_accept, srv, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = osmo_fd_register(bfd);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_ERROR, "Could not register listen fd: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ close(bfd->fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ bfd->fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_INFO, "Started listening on Lower Layer Unix Domain Socket: %s\n", srv->addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Allocate a primitive of given type and its associated msgb.</span><br><span style="color: hsl(120, 100%, 40%);">+* \param[in] srv The osmo_prim_srv instance where message is to be sent through</span><br><span style="color: hsl(120, 100%, 40%);">+* \param[in] msg msgb containing osmo_prim_hdr plus extra content, allocated through \ref osmo_prim_pkt_alloc()</span><br><span style="color: hsl(120, 100%, 40%);">+* \returns zero on success, negative on error */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_prim_srv_send(struct osmo_prim_srv *srv, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fd *conn_bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_prim_hdr *oph;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_prim_pkt_hdr *pkth;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int sap;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int primitive;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum osmo_prim_operation operation;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!srv) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_INFO, "UD socket not created, dropping message\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ conn_bfd = &srv->conn_bfd;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (conn_bfd->fd <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGSRV(srv, LOGL_NOTICE, "UD socket not connected, dropping message\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Serialize the oph: */</span><br><span style="color: hsl(120, 100%, 40%);">+ oph = (struct osmo_prim_hdr *)msgb_data(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(oph && msgb_length(msg) >= sizeof(*oph));</span><br><span style="color: hsl(120, 100%, 40%);">+ sap = oph->sap;</span><br><span style="color: hsl(120, 100%, 40%);">+ primitive = oph->primitive;</span><br><span style="color: hsl(120, 100%, 40%);">+ operation = oph->operation;</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_pull(msg, sizeof(*oph));</span><br><span style="color: hsl(120, 100%, 40%);">+ pkth = (struct osmo_prim_pkt_hdr *)msgb_push(msg, sizeof(*pkth));</span><br><span style="color: hsl(120, 100%, 40%);">+ pkth->sap = sap;</span><br><span style="color: hsl(120, 100%, 40%);">+ pkth->primitive = primitive;</span><br><span style="color: hsl(120, 100%, 40%);">+ pkth->operation = operation;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Finally enqueue the msg */</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_enqueue(&srv->upqueue, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_write_enable(conn_bfd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmo-netif/+/26426">change 26426</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmo-netif/+/26426"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: libosmo-netif </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I7cab15ac092e45a256c4f0bab11b3962df861044 </div>
<div style="display:none"> Gerrit-Change-Number: 26426 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>