<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/mncc-python/+/17402">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">initial checkin of 'osmo-rtpsource' program<br><br>osmo-rtpsource is a small utility program which is generating<br>RTP flows at a constant rate of 20ms, as required in most IP based<br>telphony.  The payload currently is hard-coded.<br><br>Change-Id: Id4e292ddfd5aa58754382b2380558993b2ddf07a<br>---<br>A rtpsource/Makefile<br>A rtpsource/ctrl_if.c<br>A rtpsource/internal.h<br>A rtpsource/rtpsource.c<br>4 files changed, 438 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/mncc-python refs/changes/02/17402/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/rtpsource/Makefile b/rtpsource/Makefile</span><br><span>new file mode 100644</span><br><span>index 0000000..9972325</span><br><span>--- /dev/null</span><br><span>+++ b/rtpsource/Makefile</span><br><span>@@ -0,0 +1,15 @@</span><br><span style="color: hsl(120, 100%, 40%);">+OSMO_CFLAGS:=$(shell pkg-config --cflags libosmocore libosmoctrl libosmotrau)</span><br><span style="color: hsl(120, 100%, 40%);">+OSMO_LIBS:=$(shell pkg-config --libs libosmocore libosmoctrl libosmotrau)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+CFLAGS:= -g -Wall $(OSMO_CFLAGS)</span><br><span style="color: hsl(120, 100%, 40%);">+LIBS:= $(OSMO_LIBS)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+rtpsource: rtpsource.o ctrl_if.o</span><br><span style="color: hsl(120, 100%, 40%);">+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)</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%);">+%.o: %.c</span><br><span style="color: hsl(120, 100%, 40%);">+       $(CC) $(CFLAGS) -o $@ -c $^</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+clean:</span><br><span style="color: hsl(120, 100%, 40%);">+ @rm -f rtpsource *.o</span><br><span>diff --git a/rtpsource/ctrl_if.c b/rtpsource/ctrl_if.c</span><br><span>new file mode 100644</span><br><span>index 0000000..708fb02</span><br><span>--- /dev/null</span><br><span>+++ b/rtpsource/ctrl_if.c</span><br><span>@@ -0,0 +1,131 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* CTRL interface of rtpsource program</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</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 General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 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 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 General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</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%);">+#include <osmocom/ctrl/control_cmd.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "internal.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+CTRL_CMD_DEFINE_WO_NOVRF(rtp_create, "rtp_create");</span><br><span style="color: hsl(120, 100%, 40%);">+static int set_rtp_create(struct ctrl_cmd *cmd, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct rtp_connection *conn;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *cname = cmd->value;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (find_connection_by_cname(g_rss, cname)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         cmd->reply = "Connection already exists for cname";</span><br><span style="color: hsl(120, 100%, 40%);">+              return CTRL_CMD_ERROR;</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%);">+   conn = create_connection(g_rss, cname);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!conn) {</span><br><span style="color: hsl(120, 100%, 40%);">+          cmd->reply = "Error creating RTP connection";</span><br><span style="color: hsl(120, 100%, 40%);">+            return CTRL_CMD_ERROR;</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%);">+   /* Respond */</span><br><span style="color: hsl(120, 100%, 40%);">+ cmd->reply = talloc_asprintf(cmd, "%s,%s,%d", conn->cname, conn->local_host, conn->local_port);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CTRL_CMD_REPLY;</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%);">+CTRL_CMD_DEFINE_WO_NOVRF(rtp_connect, "rtp_connect");</span><br><span style="color: hsl(120, 100%, 40%);">+static int set_rtp_connect(struct ctrl_cmd *cmd, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rtp_connection *conn;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *cname, *remote_host, *remote_port, *pt;</span><br><span style="color: hsl(120, 100%, 40%);">+   char *tmp, *saveptr;</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%);">+     tmp = talloc_strdup(cmd, cmd->value);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* FIXME: parse command */</span><br><span style="color: hsl(120, 100%, 40%);">+    cname = strtok_r(tmp, ",", &saveptr);</span><br><span style="color: hsl(120, 100%, 40%);">+   remote_host = strtok_r(NULL, ",", &saveptr);</span><br><span style="color: hsl(120, 100%, 40%);">+    remote_port = strtok_r(NULL, ",", &saveptr);</span><br><span style="color: hsl(120, 100%, 40%);">+    pt = strtok_r(NULL, ",", &saveptr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!cname || !remote_host || !remote_port || !pt) {</span><br><span style="color: hsl(120, 100%, 40%);">+          cmd->reply = "Format is cname,remote_host,remote_port,pt";</span><br><span style="color: hsl(120, 100%, 40%);">+               talloc_free(tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+             return CTRL_CMD_ERROR;</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%);">+   conn = find_connection_by_cname(g_rss, cname);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!conn) {</span><br><span style="color: hsl(120, 100%, 40%);">+          cmd->reply = "Error finding RTP connection for connect";</span><br><span style="color: hsl(120, 100%, 40%);">+         talloc_free(tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+             return CTRL_CMD_ERROR;</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 = connect_connection(conn, remote_host, atoi(remote_port), atoi(pt));</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              cmd->reply = "Error binding RTP connection";</span><br><span style="color: hsl(120, 100%, 40%);">+             talloc_free(tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+             return CTRL_CMD_ERROR;</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%);">+   /* Respond */</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+     cmd->reply = talloc_asprintf(cmd, "%s,%s,%d,%d", conn->cname, conn->remote_host,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   conn->remote_port, conn->rtp_pt);</span><br><span style="color: hsl(120, 100%, 40%);">+       return CTRL_CMD_REPLY;</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%);">+CTRL_CMD_DEFINE_WO_NOVRF(rtp_delete, "rtp_delete");</span><br><span style="color: hsl(120, 100%, 40%);">+static int set_rtp_delete(struct ctrl_cmd *cmd, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct rtp_connection *conn;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *cname = cmd->value;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  conn = find_connection_by_cname(g_rss, cname);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!conn) {</span><br><span style="color: hsl(120, 100%, 40%);">+          cmd->reply = "Error finding RTP connection for delete";</span><br><span style="color: hsl(120, 100%, 40%);">+          return CTRL_CMD_ERROR;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     cmd->reply = talloc_asprintf(cmd, "%s", conn->cname);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       delete_connection(conn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Respond */</span><br><span style="color: hsl(120, 100%, 40%);">+ return CTRL_CMD_REPLY;</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%);">+</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 rtpsource_ctrl_cmds_install(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</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%);">+     rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_rtp_create);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               goto end;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_rtp_connect);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               goto end;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_rtp_delete);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               goto end;</span><br><span style="color: hsl(120, 100%, 40%);">+end:</span><br><span style="color: hsl(120, 100%, 40%);">+       return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/rtpsource/internal.h b/rtpsource/internal.h</span><br><span>new file mode 100644</span><br><span>index 0000000..788b695</span><br><span>--- /dev/null</span><br><span>+++ b/rtpsource/internal.h</span><br><span>@@ -0,0 +1,46 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/trau/osmo_ortp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/ctrl/control_if.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+ DMAIN,</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 rtp_connection {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     struct osmo_rtp_socket *rtp_sock;</span><br><span style="color: hsl(120, 100%, 40%);">+     char *cname;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        char *local_host;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint16_t local_port;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        char *remote_host;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint16_t remote_port;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t rtp_pt;</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 rtpsource_state {</span><br><span style="color: hsl(120, 100%, 40%);">+       struct llist_head connections;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_fd timer_ofd;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ctrl_handle *ctrl;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+extern struct rtpsource_state *g_rss;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct rtp_connection *find_connection_by_cname(struct rtpsource_state *rss, const char *cname);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct rtp_connection *create_connection(struct rtpsource_state *rss, const char *cname);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int connect_connection(struct rtp_connection *conn, const char *remote_host,</span><br><span style="color: hsl(120, 100%, 40%);">+                 uint16_t remote_port, uint8_t pt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void delete_connection(struct rtp_connection *conn);</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 rtpsource_ctrl_cmds_install(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define CLOGP(conn, subsys, lvl, fmt, args ...) \</span><br><span style="color: hsl(120, 100%, 40%);">+   LOGP(subsys, lvl, "[%s]: " fmt, (conn)->cname, ## args)</span><br><span>diff --git a/rtpsource/rtpsource.c b/rtpsource/rtpsource.c</span><br><span>new file mode 100644</span><br><span>index 0000000..7eb39ad</span><br><span>--- /dev/null</span><br><span>+++ b/rtpsource/rtpsource.c</span><br><span>@@ -0,0 +1,246 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* rtpsource program: RTP load generator</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program binds a CTRL interface to 127.0.0.1:11111 and waits for</span><br><span style="color: hsl(120, 100%, 40%);">+ * an external entity to issue CTRL commands, such as rtp_create, rtp_connect</span><br><span style="color: hsl(120, 100%, 40%);">+ * and rtp_delete.  Those commands are used to create+bind, connect and destroy</span><br><span style="color: hsl(120, 100%, 40%);">+ * local RTP connections.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Each connection will send a RTP frame with dummy payload every 20ms.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This is useful for load testing scenarios</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</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 General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 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 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 General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</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%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></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 <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/signal.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/linuxlist.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/application.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/stats.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/ctrl/control_if.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/trau/osmo_ortp.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "internal.h"</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%);">+/* find a connection based on its CNAME */</span><br><span style="color: hsl(120, 100%, 40%);">+struct rtp_connection *find_connection_by_cname(struct rtpsource_state *rss, const char *cname)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct rtp_connection *conn;</span><br><span style="color: hsl(120, 100%, 40%);">+  llist_for_each_entry(conn, &rss->connections, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!strcmp(cname, conn->cname))</span><br><span style="color: hsl(120, 100%, 40%);">+                   return conn;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* create a new RTP connection for given CNAME; includes binding of local RTP port */</span><br><span style="color: hsl(120, 100%, 40%);">+struct rtp_connection *create_connection(struct rtpsource_state *rss, const char *cname)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rtp_connection *conn;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *host;</span><br><span style="color: hsl(120, 100%, 40%);">+     int port;</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%);">+     OSMO_ASSERT(!find_connection_by_cname(rss, cname));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ conn = talloc_zero(rss, struct rtp_connection);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(conn);</span><br><span style="color: hsl(120, 100%, 40%);">+    conn->cname = talloc_strdup(conn, cname);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        conn->rtp_sock = osmo_rtp_socket_create(conn, OSMO_RTP_F_POLL);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(conn->rtp_sock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = osmo_rtp_socket_bind(conn->rtp_sock, "127.23.23.23", -1);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = osmo_rtp_get_bound_addr(conn->rtp_sock, &host, &port);</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(port >= 0 && port <= 0xffff);</span><br><span style="color: hsl(120, 100%, 40%);">+       conn->local_port = port;</span><br><span style="color: hsl(120, 100%, 40%);">+   conn->local_host = talloc_strdup(conn, host);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_rtp_set_source_desc(conn->rtp_sock, conn->cname, "rtpsource", NULL, NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 NULL, "osmo-rtpsource", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   llist_add_tail(&conn->list, &rss->connections);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       CLOGP(conn, DMAIN, LOGL_INFO, "Created RTP connection; local=%s:%u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              conn->local_host, conn->local_port);</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%);">+        return conn;</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%);">+/* connect a RTP connection to a given remote peer */</span><br><span style="color: hsl(120, 100%, 40%);">+int connect_connection(struct rtp_connection *conn, const char *remote_host,</span><br><span style="color: hsl(120, 100%, 40%);">+                        uint16_t remote_port, uint8_t pt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</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%);">+     conn->remote_host = talloc_strdup(conn, remote_host);</span><br><span style="color: hsl(120, 100%, 40%);">+      conn->remote_port = remote_port;</span><br><span style="color: hsl(120, 100%, 40%);">+   conn->rtp_pt = pt;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = osmo_rtp_socket_connect(conn->rtp_sock, conn->remote_host, conn->remote_port);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = osmo_rtp_socket_set_pt(conn->rtp_sock, conn->rtp_pt);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       CLOGP(conn, DMAIN, LOGL_INFO, "Connected RTP connection; remote=%s:%u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+           conn->remote_host, conn->remote_port);</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%);">+/* delete a RTP connection */</span><br><span style="color: hsl(120, 100%, 40%);">+void delete_connection(struct rtp_connection *conn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *prefix = talloc_asprintf(conn, "[%s]: STATS: ", conn->cname);</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_rtp_socket_log_stats(conn->rtp_sock, DMAIN, LOGL_INFO, prefix);</span><br><span style="color: hsl(120, 100%, 40%);">+       talloc_free(prefix);</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_rtp_socket_free(conn->rtp_sock);</span><br><span style="color: hsl(120, 100%, 40%);">+      conn->rtp_sock = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   CLOGP(conn, DMAIN, LOGL_INFO, "Deleted RTP connection\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        llist_del(&conn->list);</span><br><span style="color: hsl(120, 100%, 40%);">+        talloc_free(conn);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* called every 20ms at timerfd expiration */</span><br><span style="color: hsl(120, 100%, 40%);">+static int timerfd_cb(struct osmo_fd *ofd, unsigned int priv_nr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct rtpsource_state *rss = ofd->data;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct rtp_connection *conn;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint64_t expire_count;</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%);">+     /* read from timerfd: number of expirations of periodic timer */</span><br><span style="color: hsl(120, 100%, 40%);">+      rc = read(ofd->fd, (void *) &expire_count, sizeof(expire_count));</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rc < 0 && errno == EAGAIN)</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%);">+   if (expire_count > 1)</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DMAIN, LOGL_ERROR, "Timer expire_count=%"PRIu64" != 1\n", expire_count);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* iterate over all RTP connections and send one frame each */</span><br><span style="color: hsl(120, 100%, 40%);">+        llist_for_each_entry(conn, &rss->connections, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+          int i;</span><br><span style="color: hsl(120, 100%, 40%);">+                /* TODO: have different sources (file+name, ...) */</span><br><span style="color: hsl(120, 100%, 40%);">+           const uint8_t payload[33];</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_rtp_send_frame_ext(conn->rtp_sock, payload, sizeof(payload), 160, false);</span><br><span style="color: hsl(120, 100%, 40%);">+             /* make sure RTP clock advances correctly, even if we missed transmit of some */</span><br><span style="color: hsl(120, 100%, 40%);">+              for (i = 1; i < expire_count; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+                 osmo_rtp_skipped_frame(conn->rtp_sock, 160);</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%);">+static const struct log_info_cat rtpsource_cat[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+  [DMAIN] = {</span><br><span style="color: hsl(120, 100%, 40%);">+           .name = "DMAIN",</span><br><span style="color: hsl(120, 100%, 40%);">+            .description ="Main Program",</span><br><span style="color: hsl(120, 100%, 40%);">+               .enabled = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .loglevel = LOGL_INFO,</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%);">+const struct log_info rtpsource_log_info = {</span><br><span style="color: hsl(120, 100%, 40%);">+        .filter_fn = NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+    .cat = rtpsource_cat,</span><br><span style="color: hsl(120, 100%, 40%);">+ .num_cat = ARRAY_SIZE(rtpsource_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%);">+struct rtpsource_state *g_rss;</span><br><span style="color: hsl(120, 100%, 40%);">+static void *g_tall_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void signal_handler(int signal)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (signal) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case SIGABRT:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* in case of abort, we want to obtain a talloc report</span><br><span style="color: hsl(120, 100%, 40%);">+                 * and then return to the caller, who will abort the process */</span><br><span style="color: hsl(120, 100%, 40%);">+       case SIGUSR1:</span><br><span style="color: hsl(120, 100%, 40%);">+         talloc_report_full(g_tall_ctx, stderr);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</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%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int main(int argc, char **argv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct timespec interval = {</span><br><span style="color: hsl(120, 100%, 40%);">+          .tv_sec = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+          .tv_nsec = 20*1000*1000, /* every 20ms */</span><br><span style="color: hsl(120, 100%, 40%);">+     };</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%);">+     signal(SIGUSR1, &signal_handler);</span><br><span style="color: hsl(120, 100%, 40%);">+ signal(SIGABRT, &signal_handler);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       talloc_enable_null_tracking();</span><br><span style="color: hsl(120, 100%, 40%);">+        g_tall_ctx = talloc_named_const(NULL, 1, "rtpsource");</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(g_tall_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    msgb_talloc_ctx_init(g_tall_ctx, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  //osmo_signal_talloc_ctx_init(g_tall_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_init_logging2(g_tall_ctx, &rtpsource_log_info);</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_fsm_log_timeouts(true);</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_fsm_log_addr(true);</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_stats_init(g_tall_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_rtp_init(g_tall_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  g_rss = talloc_zero(g_tall_ctx, struct rtpsource_state);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(g_rss);</span><br><span style="color: hsl(120, 100%, 40%);">+   INIT_LLIST_HEAD(&g_rss->connections);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Create CTRL interface */</span><br><span style="color: hsl(120, 100%, 40%);">+   //g_rss->ctrl = ctrl_interface_setup_dynip(g_rss, ctrl_vty_get_bind_addr(), 11111, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+  g_rss->ctrl = ctrl_interface_setup_dynip(g_rss, "127.0.0.1", 11111, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(g_rss->ctrl);</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = rtpsource_ctrl_cmds_install();</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* create + register timerfd to expire every 20ms */</span><br><span style="color: hsl(120, 100%, 40%);">+  g_rss->timer_ofd.fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = osmo_timerfd_setup(&g_rss->timer_ofd, timerfd_cb, g_rss);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = osmo_timerfd_schedule(&g_rss->timer_ofd, NULL, &interval);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+           osmo_select_main(0);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</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/mncc-python/+/17402">change 17402</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/mncc-python/+/17402"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: mncc-python </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Id4e292ddfd5aa58754382b2380558993b2ddf07a </div>
<div style="display:none"> Gerrit-Change-Number: 17402 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>