<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>