<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-msc/+/15947">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  neels: Looks good to me, approved
  pespin: Looks good to me, but someone else must approve
  laforge: Looks good to me, but someone else must approve

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add sdp_msg API: SDP parsing/composition<br><br>Rationale: in order to add full SDP to the MNCC protocol (upcoming patch<br>I8c3b2de53ffae4ec3a66b9dabf308c290a2c999f), we need to parse and compose SDP<br>messages. Obviously, libosmo-mgcp-client already contains similar code, but<br>that is unfortunately heavily glued to the actual MGCP implementation. The<br>simplest solution is to create this separate implementation, copy-pasting from<br>the existing libosmo-mgcp-client code as is convenient.<br><br>This API is added here to probe whether it works well. When it does, the<br>intention is to "move it up" to osmo-mgw and overhaul the SDP parsing in our<br>MGCP client and MGCP server APIs using this same API.<br><br>Change-Id: If3ce23cd5bab15e2ab4c52ef3e4c75979dffe931<br>---<br>M configure.ac<br>M include/osmocom/msc/Makefile.am<br>A include/osmocom/msc/sdp_msg.h<br>M src/libmsc/Makefile.am<br>A src/libmsc/sdp_msg.c<br>M tests/Makefile.am<br>A tests/sdp_msg/Makefile.am<br>A tests/sdp_msg/sdp_msg_test.c<br>A tests/sdp_msg/sdp_msg_test.err<br>A tests/sdp_msg/sdp_msg_test.ok<br>M tests/testsuite.at<br>11 files changed, 1,846 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configure.ac b/configure.ac</span><br><span>index 5aa652d..ee80900 100644</span><br><span>--- a/configure.ac</span><br><span>+++ b/configure.ac</span><br><span>@@ -254,6 +254,7 @@</span><br><span>     tests/db_sms/Makefile</span><br><span>     tests/sms_queue/Makefile</span><br><span>     tests/msc_vlr/Makefile</span><br><span style="color: hsl(120, 100%, 40%);">+    tests/sdp_msg/Makefile</span><br><span>     doc/Makefile</span><br><span>     doc/examples/Makefile</span><br><span>     doc/manuals/Makefile</span><br><span>diff --git a/include/osmocom/msc/Makefile.am b/include/osmocom/msc/Makefile.am</span><br><span>index 0d7d45c..faf1048 100644</span><br><span>--- a/include/osmocom/msc/Makefile.am</span><br><span>+++ b/include/osmocom/msc/Makefile.am</span><br><span>@@ -39,6 +39,7 @@</span><br><span>    rrlp.h \</span><br><span>     rtp_stream.h \</span><br><span>       sccp_ran.h \</span><br><span style="color: hsl(120, 100%, 40%);">+  sdp_msg.h \</span><br><span>  sgs_iface.h \</span><br><span>        sgs_server.h \</span><br><span>       sgs_vty.h \</span><br><span>diff --git a/include/osmocom/msc/sdp_msg.h b/include/osmocom/msc/sdp_msg.h</span><br><span>new file mode 100644</span><br><span>index 0000000..7ac6036</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/msc/sdp_msg.h</span><br><span>@@ -0,0 +1,68 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Minimalistic SDP parse/compose API, focused on GSM audio codecs */</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 <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/sockaddr_str.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct value_string sdp_msg_payload_type_names[];</span><br><span style="color: hsl(120, 100%, 40%);">+static inline const char *sdp_msg_payload_type_name(unsigned int payload_type)</span><br><span style="color: hsl(120, 100%, 40%);">+{ return get_value_string(sdp_msg_payload_type_names, payload_type); }</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_subtype_name_to_payload_type(const char *subtype_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct sdp_audio_codec {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int payload_type;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Like "GSM", "AMR", "EFR", ... */</span><br><span style="color: hsl(120, 100%, 40%);">+     char subtype_name[16];</span><br><span style="color: hsl(120, 100%, 40%);">+        unsigned int rate;</span><br><span style="color: hsl(120, 100%, 40%);">+    char fmtp[64];</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 sdp_audio_codecs {</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int count;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct sdp_audio_codec codec[16];</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 sdp_msg {</span><br><span style="color: hsl(120, 100%, 40%);">+     struct osmo_sockaddr_str rtp;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int ptime;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct sdp_audio_codecs audio_codecs;</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 foreach_sdp_audio_codec(/* struct sdp_audio_codec* */ CODEC, \</span><br><span style="color: hsl(120, 100%, 40%);">+                           /* struct sdp_audio_codecs* */ AC) \</span><br><span style="color: hsl(120, 100%, 40%);">+  for (CODEC = (AC)->codec; \</span><br><span style="color: hsl(120, 100%, 40%);">+             (CODEC - (AC)->codec) < OSMO_MIN((AC)->count, ARRAY_SIZE((AC)->codec)); \</span><br><span style="color: hsl(120, 100%, 40%);">+         CODEC++)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const char *sdp_msg_line_end(const char *src);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct sdp_audio_codec *sdp_audio_codec_add(struct sdp_audio_codecs *ac, unsigned int payload_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      const char *subtype_name, unsigned int rate, const char *fmtp);</span><br><span style="color: hsl(120, 100%, 40%);">+struct sdp_audio_codec *sdp_audio_codec_add_copy(struct sdp_audio_codecs *ac,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             const struct sdp_audio_codec *codec);</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_audio_codec_remove(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec);</span><br><span style="color: hsl(120, 100%, 40%);">+struct sdp_audio_codec *sdp_audio_codec_by_payload_type(struct sdp_audio_codecs *ac,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   unsigned int payload_type, bool create);</span><br><span style="color: hsl(120, 100%, 40%);">+struct sdp_audio_codec *sdp_audio_codec_by_descr(struct sdp_audio_codecs *ac,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                const struct sdp_audio_codec *codec);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void sdp_audio_codecs_intersection(struct sdp_audio_codecs *ac_dest, const struct sdp_audio_codecs *ac_other,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  bool translate_payload_type_numbers);</span><br><span style="color: hsl(120, 100%, 40%);">+void sdp_audio_codecs_select(struct sdp_audio_codecs *ac, struct sdp_audio_codec *codec);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_msg_to_str(char *dst, size_t dst_size, const struct sdp_msg *sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_msg_from_str(struct sdp_msg *sdp, const char *src);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_audio_codec_name_buf(char *buf, size_t buflen, const struct sdp_audio_codec *codec);</span><br><span style="color: hsl(120, 100%, 40%);">+char *sdp_audio_codec_name_c(void *ctx, const struct sdp_audio_codec *codec);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *sdp_audio_codec_name(const struct sdp_audio_codec *codec);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_audio_codecs_name_buf(char *buf, size_t buflen, const struct sdp_audio_codecs *ac);</span><br><span style="color: hsl(120, 100%, 40%);">+char *sdp_audio_codecs_name_c(void *ctx, const struct sdp_audio_codecs *ac);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *sdp_audio_codecs_name(const struct sdp_audio_codecs *ac);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_msg_name_buf(char *buf, size_t buflen, const struct sdp_msg *sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+char *sdp_msg_name_c(void *ctx, const struct sdp_msg *sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *sdp_msg_name(const struct sdp_msg *sdp);</span><br><span>diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am</span><br><span>index d834896..e6a2dc1 100644</span><br><span>--- a/src/libmsc/Makefile.am</span><br><span>+++ b/src/libmsc/Makefile.am</span><br><span>@@ -64,6 +64,7 @@</span><br><span>  ran_peer.c \</span><br><span>         rrlp.c \</span><br><span>     rtp_stream.c \</span><br><span style="color: hsl(120, 100%, 40%);">+        sdp_msg.c \</span><br><span>  silent_call.c \</span><br><span>      sms_queue.c \</span><br><span>        transaction.c \</span><br><span>diff --git a/src/libmsc/sdp_msg.c b/src/libmsc/sdp_msg.c</span><br><span>new file mode 100644</span><br><span>index 0000000..7880978</span><br><span>--- /dev/null</span><br><span>+++ b/src/libmsc/sdp_msg.c</span><br><span>@@ -0,0 +1,576 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Minimalistic SDP parse/compose implementation, focused on GSM audio codecs */</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@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%);">+ * SPDX-License-Identifier: AGPL-3.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Neels Hofmeyr</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/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 <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.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/msc/debug.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/msc/sdp_msg.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Compare name, rate and fmtp, returning typical cmp result: 0 on match, and -1 / 1 on mismatch.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Do *not* compare the payload_type number.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The fmtp is only string-compared -- e.g. if AMR parameters appear in a different order, it amounts to a mismatch even</span><br><span style="color: hsl(120, 100%, 40%);">+ * though all parameters are the same. */</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b)</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%);">+       if (a == b)</span><br><span style="color: hsl(120, 100%, 40%);">+           return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!a)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!b)</span><br><span style="color: hsl(120, 100%, 40%);">+               return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = strncmp(a->subtype_name, b->subtype_name, sizeof(a->subtype_name));</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc)</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 (a->rate < b->rate)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (a->rate > b->rate)</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%);">+   rc = strncmp(a->fmtp, b->fmtp, sizeof(a->fmtp));</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc)</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%);">+  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%);">+/* Given a predefined fixed payload_type number, add an SDP audio codec entry, if not present yet.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The payload_type must exist in sdp_msg_payload_type_names.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return the audio codec created or already existing for this payload type number.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct sdp_audio_codec *sdp_audio_codec_add(struct sdp_audio_codecs *ac, unsigned int payload_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                                          const char *subtype_name, unsigned int rate, const char *fmtp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct sdp_audio_codec *codec;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Does an entry already exist? */</span><br><span style="color: hsl(120, 100%, 40%);">+    codec = sdp_audio_codec_by_payload_type(ac, payload_type, false);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (codec) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* Already exists, sanity check */</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!codec->subtype_name[0])</span><br><span style="color: hsl(120, 100%, 40%);">+                       OSMO_STRLCPY_ARRAY(codec->subtype_name, subtype_name);</span><br><span style="color: hsl(120, 100%, 40%);">+             else if (strcmp(codec->subtype_name, subtype_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* There already is an entry with this payload_type number but a mismatching subtype_name. That is</span><br><span style="color: hsl(120, 100%, 40%);">+                     * weird, rather abort. */</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%);">+             if (codec->rate != rate</span><br><span style="color: hsl(120, 100%, 40%);">+                || (fmtp && strcmp(fmtp, codec->fmtp))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* Mismatching details. Rather abort */</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%);">+             return codec;</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%);">+   /* None exists, create codec entry for this payload type number */</span><br><span style="color: hsl(120, 100%, 40%);">+    codec = sdp_audio_codec_by_payload_type(ac, payload_type, true);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* NULL means unable to add an entry */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!codec)</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%);">+        OSMO_STRLCPY_ARRAY(codec->subtype_name, subtype_name);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (fmtp)</span><br><span style="color: hsl(120, 100%, 40%);">+             OSMO_STRLCPY_ARRAY(codec->fmtp, fmtp);</span><br><span style="color: hsl(120, 100%, 40%);">+     return codec;</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 sdp_audio_codec *sdp_audio_codec_add_copy(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return sdp_audio_codec_add(ac, codec->payload_type, codec->subtype_name, codec->rate,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   codec->fmtp[0] ? codec->fmtp : 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%);">+struct sdp_audio_codec *sdp_audio_codec_by_payload_type(struct sdp_audio_codecs *ac, unsigned int payload_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  bool create)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct sdp_audio_codec *codec;</span><br><span style="color: hsl(120, 100%, 40%);">+        foreach_sdp_audio_codec(codec, ac) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (codec->payload_type == payload_type)</span><br><span style="color: hsl(120, 100%, 40%);">+                   return codec;</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 (!create)</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%);">+        /* Not found; codec points after the last entry now. */</span><br><span style="color: hsl(120, 100%, 40%);">+       if ((codec - ac->codec) >= ARRAY_SIZE(ac->codec))</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%);">+        *codec = (struct sdp_audio_codec){</span><br><span style="color: hsl(120, 100%, 40%);">+            .payload_type = payload_type,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rate = 8000,</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%);">+  ac->count = (codec - ac->codec) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    return codec;</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 a given sdp_msg's codec entry that matches the subtype_name, rate and fmtp of the given codec, or NULL if no</span><br><span style="color: hsl(120, 100%, 40%);">+ * match is found. Comparison is made by sdp_audio_codec_cmp(). */</span><br><span style="color: hsl(120, 100%, 40%);">+struct sdp_audio_codec *sdp_audio_codec_by_descr(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct sdp_audio_codec *i;</span><br><span style="color: hsl(120, 100%, 40%);">+    foreach_sdp_audio_codec(i, ac) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (!sdp_audio_codec_cmp(i, codec))</span><br><span style="color: hsl(120, 100%, 40%);">+                   return i;</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%);">+/* Remove the codec entry pointed at by 'codec'. 'codec' must point at an entry of 'sdp' (to use an external codec</span><br><span style="color: hsl(120, 100%, 40%);">+ * instance, use sdp_audio_codec_by_descr()).</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return 0 on success, -ENOENT if codec does not point at the sdp->codec array. */</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_audio_codec_remove(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct sdp_audio_codec *i;</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((codec < ac->codec)</span><br><span style="color: hsl(120, 100%, 40%);">+     || ((codec - ac->codec) >= OSMO_MIN(ac->count, ARRAY_SIZE(ac->codec))))</span><br><span style="color: hsl(120, 100%, 40%);">+               return -ENOENT;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Move all following entries one up */</span><br><span style="color: hsl(120, 100%, 40%);">+       ac->count--;</span><br><span style="color: hsl(120, 100%, 40%);">+       foreach_sdp_audio_codec(i, ac) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (i < codec)</span><br><span style="color: hsl(120, 100%, 40%);">+                     continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             *i = *(i+1);</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%);">+/* Convert struct sdp_msg to the actual SDP protocol representation */</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_msg_to_str(char *dst, size_t dst_size, const struct sdp_msg *sdp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  const struct sdp_audio_codec *codec;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct osmo_strbuf sb = { .buf = dst, .len = dst_size };</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *ip = sdp->rtp.ip[0] ? sdp->rtp.ip : "0.0.0.0";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_STRBUF_PRINTF(sb,</span><br><span style="color: hsl(120, 100%, 40%);">+                           "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                           "o=OsmoMSC 0 0 IN IP4 %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                    "c=IN IP4 %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                           "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                         "m=audio %d RTP/AVP",</span><br><span style="color: hsl(120, 100%, 40%);">+                       ip, ip,</span><br><span style="color: hsl(120, 100%, 40%);">+                       sdp->rtp.port);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Append all payload type numbers to 'm=audio <port> RTP/AVP 3 4 112' line */</span><br><span style="color: hsl(120, 100%, 40%);">+  foreach_sdp_audio_codec(codec, &sdp->audio_codecs)</span><br><span style="color: hsl(120, 100%, 40%);">+             OSMO_STRBUF_PRINTF(sb, " %d", codec->payload_type);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_STRBUF_PRINTF(sb, "\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Add details for all codecs */</span><br><span style="color: hsl(120, 100%, 40%);">+      foreach_sdp_audio_codec(codec, &sdp->audio_codecs) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (codec->subtype_name[0]) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      OSMO_STRBUF_PRINTF(sb, "a=rtpmap:%d %s/%d\r\n", codec->payload_type, codec->subtype_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        codec->rate > 0? codec->rate : 8000);</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 (codec->fmtp[0])</span><br><span style="color: hsl(120, 100%, 40%);">+                        OSMO_STRBUF_PRINTF(sb, "a=fmtp:%d %s\r\n", codec->payload_type, codec->fmtp);</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_STRBUF_PRINTF(sb, "a=ptime:%d\r\n", sdp->ptime > 0? sdp->ptime : 20);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return sb.chars_needed;</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 the first line ending (or the end of the string) at or after the given string position. */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *sdp_msg_line_end(const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *line_end = strchr(src, '\r');</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!line_end)</span><br><span style="color: hsl(120, 100%, 40%);">+                line_end = strchr(src, '\n');</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!line_end)</span><br><span style="color: hsl(120, 100%, 40%);">+                line_end = src + strlen(src);</span><br><span style="color: hsl(120, 100%, 40%);">+ return line_end;</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%);">+/* parse a line like 'a=rtpmap:0 PCMU/8000', 'a=fmtp:112 octet-align=1; mode-set=4', 'a=ptime:20'.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The src should point at the character after 'a=', e.g. at the start of 'rtpmap', 'fmtp', 'ptime'</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_parse_attrib(struct sdp_msg *sdp, const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned int payload_type;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct sdp_audio_codec *codec;</span><br><span style="color: hsl(120, 100%, 40%);">+#define A_RTPMAP "rtpmap:"</span><br><span style="color: hsl(120, 100%, 40%);">+#define A_FMTP "fmtp:"</span><br><span style="color: hsl(120, 100%, 40%);">+#define A_PTIME "ptime:"</span><br><span style="color: hsl(120, 100%, 40%);">+#define A_RTCP "rtcp:"</span><br><span style="color: hsl(120, 100%, 40%);">+#define A_SENDRECV "sendrecv"</span><br><span style="color: hsl(120, 100%, 40%);">+#define A_SENDONLY "sendonly"</span><br><span style="color: hsl(120, 100%, 40%);">+#define A_RECVONLY "recvonly"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (osmo_str_startswith(src, A_RTPMAP)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             char *audio_name;</span><br><span style="color: hsl(120, 100%, 40%);">+             unsigned int channels = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+            if (sscanf(src, A_RTPMAP "%u", &payload_type) != 1)</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%);">+             audio_name = strchr(src, ' ');</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!audio_name || audio_name >= sdp_msg_line_end(src))</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%);">+             codec = sdp_audio_codec_by_payload_type(&sdp->audio_codecs, payload_type, true);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!codec)</span><br><span style="color: hsl(120, 100%, 40%);">+                   return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             if (sscanf(audio_name, " %31[^/]/%u/%u", codec->subtype_name, &codec->rate, &channels) < 1)</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%);">+             if (channels != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                    return -ENOTSUP;</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%);">+   else if (osmo_str_startswith(src, A_FMTP)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          char *fmtp_str;</span><br><span style="color: hsl(120, 100%, 40%);">+               const char *line_end = sdp_msg_line_end(src);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (sscanf(src, A_FMTP "%u", &payload_type) != 1)</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%);">+             fmtp_str = strchr(src, ' ');</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!fmtp_str)</span><br><span style="color: hsl(120, 100%, 40%);">+                        return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+               fmtp_str++;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (fmtp_str >= line_end)</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%);">+             codec = sdp_audio_codec_by_payload_type(&sdp->audio_codecs, payload_type, true);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!codec)</span><br><span style="color: hsl(120, 100%, 40%);">+                   return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* (+1 because osmo_strlcpy() interprets it as size including the '\0') */</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_strlcpy(codec->fmtp, fmtp_str, line_end - fmtp_str + 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%);">+   else if (osmo_str_startswith(src, A_PTIME)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (sscanf(src, A_PTIME "%u", &sdp->ptime) != 1)</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%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   else if (osmo_str_startswith(src, A_RTCP)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* TODO? */</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%);">+   else if (osmo_str_startswith(src, A_SENDRECV)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* TODO? */</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%);">+   else if (osmo_str_startswith(src, A_SENDONLY)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* TODO? */</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%);">+   else if (osmo_str_startswith(src, A_RECVONLY)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* TODO? */</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 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 struct value_string sdp_msg_payload_type_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    { 0, "PCMU" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { 3, "GSM" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { 8, "PCMA" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { 18, "G729" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { 110, "GSM-EFR" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 111, "GSM-HR-08" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { 112, "AMR" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { 113, "AMR-WB" },</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%);">+/* Return payload type number matching given string ("AMR", "GSM", ...) or negative if not found. */</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_subtype_name_to_payload_type(const char *subtype_name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return get_string_value(sdp_msg_payload_type_names, subtype_name);</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%);">+/* Parse a line like 'm=audio 16398 RTP/AVP 0 3 8 96 112', starting after the '=' */</span><br><span style="color: hsl(120, 100%, 40%);">+static int sdp_parse_media_description(struct sdp_msg *sdp, const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        unsigned int port;</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *payload_type_str;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *line_end = sdp_msg_line_end(src);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (sscanf(src, "audio %u RTP/AVP", &port) < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+              return -ENOTSUP;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (port < 0 || port > 0xffff)</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%);">+     sdp->rtp.port = port;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* skip "audio 12345 RTP/AVP ", i.e. 3 spaces on */</span><br><span style="color: hsl(120, 100%, 40%);">+ payload_type_str = src;</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < 3; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          payload_type_str = strchr(payload_type_str, ' ');</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!payload_type_str)</span><br><span style="color: hsl(120, 100%, 40%);">+                        return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+               while (*payload_type_str == ' ')</span><br><span style="color: hsl(120, 100%, 40%);">+                      payload_type_str++;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (payload_type_str >= line_end)</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Parse listing of payload type numbers after "RTP/AVP" */</span><br><span style="color: hsl(120, 100%, 40%);">+ while (payload_type_str < line_end) {</span><br><span style="color: hsl(120, 100%, 40%);">+              unsigned int payload_type;</span><br><span style="color: hsl(120, 100%, 40%);">+            struct sdp_audio_codec *codec;</span><br><span style="color: hsl(120, 100%, 40%);">+                const char *subtype_name;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (sscanf(payload_type_str, "%u", &payload_type) < 1)</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%);">+             codec = sdp_audio_codec_by_payload_type(&sdp->audio_codecs, payload_type, true);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!codec)</span><br><span style="color: hsl(120, 100%, 40%);">+                   return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Fill in subtype name for fixed payload types */</span><br><span style="color: hsl(120, 100%, 40%);">+            subtype_name = get_value_string_or_null(sdp_msg_payload_type_names, codec->payload_type);</span><br><span style="color: hsl(120, 100%, 40%);">+          if (subtype_name)</span><br><span style="color: hsl(120, 100%, 40%);">+                     OSMO_STRLCPY_ARRAY(codec->subtype_name, subtype_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           payload_type_str = strchr(payload_type_str, ' ');</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!payload_type_str)</span><br><span style="color: hsl(120, 100%, 40%);">+                        payload_type_str = line_end;</span><br><span style="color: hsl(120, 100%, 40%);">+          while (*payload_type_str == ' ')</span><br><span style="color: hsl(120, 100%, 40%);">+                      payload_type_str++;</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 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%);">+/* parse a line like 'c=IN IP4 192.168.11.151' starting after the '=' */</span><br><span style="color: hsl(120, 100%, 40%);">+static int sdp_parse_connection_info(struct sdp_msg *sdp, const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char ipv[10];</span><br><span style="color: hsl(120, 100%, 40%);">+ char addr_str[INET6_ADDRSTRLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+      if (sscanf(src, "IN %s %s", ipv, addr_str) < 2)</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%);">+     /* supporting only IPv4 */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (strcmp(ipv, "IP4"))</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOTSUP;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_sockaddr_str_from_str(&sdp->rtp, addr_str, sdp->rtp.port);</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%);">+/* Parse SDP string into struct sdp_msg. Return 0 on success, negative on error. */</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_msg_from_str(struct sdp_msg *sdp, const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *pos;</span><br><span style="color: hsl(120, 100%, 40%);">+      *sdp = (struct sdp_msg){};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (pos = src; pos && *pos; pos++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         char attrib;</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 (*pos == '\r' || *pos == '\n')</span><br><span style="color: hsl(120, 100%, 40%);">+                     continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Expecting only lines starting with 'X='. Not being too strict about it is probably alright. */</span><br><span style="color: hsl(120, 100%, 40%);">+             if (pos[1] != '=')</span><br><span style="color: hsl(120, 100%, 40%);">+                    goto next_line;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             attrib = *pos;</span><br><span style="color: hsl(120, 100%, 40%);">+                pos += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+             switch (attrib) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* a=... */</span><br><span style="color: hsl(120, 100%, 40%);">+                   case 'a':</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = sdp_parse_attrib(sdp, pos);</span><br><span style="color: hsl(120, 100%, 40%);">+                              break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        case 'm':</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = sdp_parse_media_description(sdp, pos);</span><br><span style="color: hsl(120, 100%, 40%);">+                           break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        case 'c':</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = sdp_parse_connection_info(sdp, pos);</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%);">+                              /* ignore any other parameters */</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%);">+           if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     size_t line_len;</span><br><span style="color: hsl(120, 100%, 40%);">+                      const char *line_end = sdp_msg_line_end(pos);</span><br><span style="color: hsl(120, 100%, 40%);">+                 pos -= 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                     line_len = line_end - pos;</span><br><span style="color: hsl(120, 100%, 40%);">+                    switch (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 case -EINVAL:</span><br><span style="color: hsl(120, 100%, 40%);">+                         LOGP(DMNCC, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "Failed to parse SDP: invalid line: %s\n", osmo_quote_str(pos, line_len));</span><br><span style="color: hsl(120, 100%, 40%);">+                             break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        case -ENOSPC:</span><br><span style="color: hsl(120, 100%, 40%);">+                         LOGP(DMNCC, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "Failed to parse SDP: no more space for: %s\n", osmo_quote_str(pos, line_len));</span><br><span style="color: hsl(120, 100%, 40%);">+                                break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        case -ENOTSUP:</span><br><span style="color: hsl(120, 100%, 40%);">+                                LOGP(DMNCC, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "Failed to parse SDP: not supported: %s\n", osmo_quote_str(pos, line_len));</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%);">+                              LOGP(DMNCC, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "Failed to parse SDP: %s\n", osmo_quote_str(pos, line_len));</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%);">+                     return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+next_line:</span><br><span style="color: hsl(120, 100%, 40%);">+         pos = strstr(pos, "\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!pos)</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%);">+   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%);">+/* Leave only those codecs in 'ac_dest' that are also present in 'ac_other'.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The matching is made by sdp_audio_codec_cmp(), i.e. payload_type numbers are not compared and fmtp parameters are</span><br><span style="color: hsl(120, 100%, 40%);">+ * compared 1:1 as plain strings.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If translate_payload_type_numbers has an effect if ac_dest and ac_other have mismatching payload_type numbers for the</span><br><span style="color: hsl(120, 100%, 40%);">+ * same SDP codec descriptions. If translate_payload_type_numbers is true, take the payload_type numbers from ac_other.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If false, keep payload_type numbers in ac_dest unchanged. */</span><br><span style="color: hsl(120, 100%, 40%);">+void sdp_audio_codecs_intersection(struct sdp_audio_codecs *ac_dest, const struct sdp_audio_codecs *ac_other,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 bool translate_payload_type_numbers)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < ac_dest->count; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          struct sdp_audio_codec *codec = &ac_dest->codec[i];</span><br><span style="color: hsl(120, 100%, 40%);">+            struct sdp_audio_codec *other;</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_ASSERT(i < ARRAY_SIZE(ac_dest->codec));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          other = sdp_audio_codec_by_descr((struct sdp_audio_codecs*)ac_other, codec);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!other) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 OSMO_ASSERT(sdp_audio_codec_remove(ac_dest, codec) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                     i--;</span><br><span style="color: hsl(120, 100%, 40%);">+                  continue;</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%);">+           /* Doing payload_type number translation of part of the intersection because it makes the algorithm</span><br><span style="color: hsl(120, 100%, 40%);">+            * simpler: we already know ac_dest is a subset of ac_other, and there is no need to resolve payload</span><br><span style="color: hsl(120, 100%, 40%);">+           * type number conflicts. */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (translate_payload_type_numbers)</span><br><span style="color: hsl(120, 100%, 40%);">+                   codec->payload_type = other->payload_type;</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%);">+/* Make sure the given codec is listed as the first codec. 'codec' must be an actual codec entry of the given audio</span><br><span style="color: hsl(120, 100%, 40%);">+ * codecs list. */</span><br><span style="color: hsl(120, 100%, 40%);">+void sdp_audio_codecs_select(struct sdp_audio_codecs *ac, struct sdp_audio_codec *codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct sdp_audio_codec tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct sdp_audio_codec *pos;</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT((codec >= ac->codec)</span><br><span style="color: hsl(120, 100%, 40%);">+                    && ((codec - ac->codec) < OSMO_MIN(ac->count, ARRAY_SIZE(ac->codec))));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Already the first? */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (codec == ac->codec)</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%);">+     tmp = *codec;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (pos = codec - 1; pos >= ac->codec; pos--)</span><br><span style="color: hsl(120, 100%, 40%);">+          pos[1] = pos[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ac->codec[0] = tmp;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Short single-line representation of an SDP audio codec, convenient for logging.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Like "AMR/8000:octet-align=1#122" */</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_audio_codec_name_buf(char *buf, size_t buflen, const struct sdp_audio_codec *codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_strbuf sb = { .buf = buf, .len = buflen };</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_STRBUF_PRINTF(sb, "%s", codec->subtype_name);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (codec->fmtp[0])</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_STRBUF_PRINTF(sb, ":%s", codec->fmtp);</span><br><span style="color: hsl(120, 100%, 40%);">+      return sb.chars_needed;</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%);">+char *sdp_audio_codec_name_c(void *ctx, const struct sdp_audio_codec *codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_NAME_C_IMPL(ctx, 32, "sdp_audio_codec_name_c-ERROR", sdp_audio_codec_name_buf, codec)</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 *sdp_audio_codec_name(const struct sdp_audio_codec *codec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   return sdp_audio_codec_name_c(OTC_SELECT, codec);</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%);">+/* Short single-line representation of a list of SDP audio codecs, convenient for logging */</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_audio_codecs_name_buf(char *buf, size_t buflen, const struct sdp_audio_codecs *ac)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_strbuf sb = { .buf = buf, .len = buflen };</span><br><span style="color: hsl(120, 100%, 40%);">+        const struct sdp_audio_codec *codec;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!ac->count)</span><br><span style="color: hsl(120, 100%, 40%);">+            OSMO_STRBUF_PRINTF(sb, "(no-codecs)");</span><br><span style="color: hsl(120, 100%, 40%);">+      foreach_sdp_audio_codec(codec, ac) {</span><br><span style="color: hsl(120, 100%, 40%);">+          bool first = (codec == ac->codec);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!first)</span><br><span style="color: hsl(120, 100%, 40%);">+                   OSMO_STRBUF_PRINTF(sb, ",");</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_STRBUF_APPEND(sb, sdp_audio_codec_name_buf, codec);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     return sb.chars_needed;</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%);">+char *sdp_audio_codecs_name_c(void *ctx, const struct sdp_audio_codecs *ac)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_NAME_C_IMPL(ctx, 128, "sdp_audio_codecs_name_c-ERROR", sdp_audio_codecs_name_buf, ac)</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 *sdp_audio_codecs_name(const struct sdp_audio_codecs *ac)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    return sdp_audio_codecs_name_c(OTC_SELECT, ac);</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%);">+/* Short single-line representation of an SDP message, convenient for logging */</span><br><span style="color: hsl(120, 100%, 40%);">+int sdp_msg_name_buf(char *buf, size_t buflen, const struct sdp_msg *sdp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct osmo_strbuf sb = { .buf = buf, .len = buflen };</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!sdp) {</span><br><span style="color: hsl(120, 100%, 40%);">+           OSMO_STRBUF_PRINTF(sb, "NULL");</span><br><span style="color: hsl(120, 100%, 40%);">+             return sb.chars_needed;</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_STRBUF_PRINTF(sb, OSMO_SOCKADDR_STR_FMT, OSMO_SOCKADDR_STR_FMT_ARGS(&sdp->rtp));</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_STRBUF_PRINTF(sb, "{");</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_STRBUF_APPEND(sb, sdp_audio_codecs_name_buf, &sdp->audio_codecs);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_STRBUF_PRINTF(sb, "}");</span><br><span style="color: hsl(120, 100%, 40%);">+        return sb.chars_needed;</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%);">+char *sdp_msg_name_c(void *ctx, const struct sdp_msg *sdp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_NAME_C_IMPL(ctx, 128, "sdp_msg_name_c-ERROR", sdp_msg_name_buf, sdp)</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 *sdp_msg_name(const struct sdp_msg *sdp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return sdp_msg_name_c(OTC_SELECT, sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/tests/Makefile.am b/tests/Makefile.am</span><br><span>index 27c1205..864ac7c 100644</span><br><span>--- a/tests/Makefile.am</span><br><span>+++ b/tests/Makefile.am</span><br><span>@@ -2,6 +2,7 @@</span><br><span>        sms_queue \</span><br><span>  msc_vlr \</span><br><span>    db_sms \</span><br><span style="color: hsl(120, 100%, 40%);">+      sdp_msg \</span><br><span>    $(NULL)</span><br><span> </span><br><span> if BUILD_SMPP</span><br><span>diff --git a/tests/sdp_msg/Makefile.am b/tests/sdp_msg/Makefile.am</span><br><span>new file mode 100644</span><br><span>index 0000000..7d8def9</span><br><span>--- /dev/null</span><br><span>+++ b/tests/sdp_msg/Makefile.am</span><br><span>@@ -0,0 +1,32 @@</span><br><span style="color: hsl(120, 100%, 40%);">+AM_CPPFLAGS = \</span><br><span style="color: hsl(120, 100%, 40%);">+       $(all_includes) \</span><br><span style="color: hsl(120, 100%, 40%);">+     -I$(top_srcdir)/include \</span><br><span style="color: hsl(120, 100%, 40%);">+     $(NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AM_CFLAGS = \</span><br><span style="color: hsl(120, 100%, 40%);">+      -Wall \</span><br><span style="color: hsl(120, 100%, 40%);">+       -ggdb3 \</span><br><span style="color: hsl(120, 100%, 40%);">+      $(LIBOSMOCORE_CFLAGS) \</span><br><span style="color: hsl(120, 100%, 40%);">+       $(NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+LDADD = \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(top_builddir)/src/libmsc/libmsc.a \</span><br><span style="color: hsl(120, 100%, 40%);">+ $(LIBOSMOCORE_LIBS) \</span><br><span style="color: hsl(120, 100%, 40%);">+ $(NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+EXTRA_DIST = \</span><br><span style="color: hsl(120, 100%, 40%);">+     sdp_msg_test.ok \</span><br><span style="color: hsl(120, 100%, 40%);">+     sdp_msg_test.err \</span><br><span style="color: hsl(120, 100%, 40%);">+    $(NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+noinst_PROGRAMS = \</span><br><span style="color: hsl(120, 100%, 40%);">+        sdp_msg_test \</span><br><span style="color: hsl(120, 100%, 40%);">+        $(NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_test_SOURCES = \</span><br><span style="color: hsl(120, 100%, 40%);">+   sdp_msg_test.c \</span><br><span style="color: hsl(120, 100%, 40%);">+      $(NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+.PHONY: update_exp</span><br><span style="color: hsl(120, 100%, 40%);">+update_exp:</span><br><span style="color: hsl(120, 100%, 40%);">+    $(builddir)/sdp_msg_test >$(srcdir)/sdp_msg_test.ok 2>$(srcdir)/sdp_msg_test.err</span><br><span>diff --git a/tests/sdp_msg/sdp_msg_test.c b/tests/sdp_msg/sdp_msg_test.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b97127a</span><br><span>--- /dev/null</span><br><span>+++ b/tests/sdp_msg/sdp_msg_test.c</span><br><span>@@ -0,0 +1,569 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/msc/sdp_msg.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct sdp_test_data {</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *sdp_input;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *expect_sdp_str;</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 void dump_sdp(const char *str, const char *prefix)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       while (str && *str) {</span><br><span style="color: hsl(120, 100%, 40%);">+         const char *line_end = sdp_msg_line_end(str);</span><br><span style="color: hsl(120, 100%, 40%);">+         while (*line_end == '\r' || *line_end == '\n')</span><br><span style="color: hsl(120, 100%, 40%);">+                        line_end++;</span><br><span style="color: hsl(120, 100%, 40%);">+           printf("%s%s\n", prefix, osmo_escape_str(str, line_end - str));</span><br><span style="color: hsl(120, 100%, 40%);">+             str = line_end;</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%);">+struct sdp_test_data sdp_tests[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+  {</span><br><span style="color: hsl(120, 100%, 40%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=- 5628250 5628250 IN IP4 192.168.11.121\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "s=-\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "c=IN IP4 192.168.11.121\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 10020 RTP/AVP 18 0 2 4 8 96 97 98 100 101\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:18 G729/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:0 PCMU/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:2 G726-32/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=rtpmap:4 G723/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:8 PCMA/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:96 G726-40/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:97 G726-24/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:98 G726-16/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:100 NSE/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:100 192-193\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtpmap:101 telephone-event/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=fmtp:101 0-15\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=sendrecv\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 192.168.11.121\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 192.168.11.121\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 10020 RTP/AVP 18 0 2 4 8 96 97 98 100 101\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:18 G729/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:0 PCMU/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:2 G726-32/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=rtpmap:4 G723/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:8 PCMA/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:96 G726-40/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:97 G726-24/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:98 G726-16/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:100 NSE/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:100 192-193\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtpmap:101 telephone-event/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=fmtp:101 0-15\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=ptime:20\r\n"</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%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=FooBar 1565090289 1565090290 IN IP4 192.168.11.151\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "s=FooBar\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "c=IN IP4 192.168.11.151\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 16398 RTP/AVP 98\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:98 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=fmtp:98 octet-align=1; mode-set=4\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtcp:16399 IN IP4 192.168.11.151\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 192.168.11.151\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 192.168.11.151\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 16398 RTP/AVP 98\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:98 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=fmtp:98 octet-align=1; mode-set=4\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=ptime:20\r\n"</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%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=FooBar 1565090289 1565090290 IN IP4 192.168.11.151\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "s=FooBar\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "c=IN IP4 192.168.11.140\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 30436 RTP/AVP 18 0 4 8 101\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtpmap:18 G729/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:0 PCMU/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:4 G723/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:8 PCMA/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:101 telephone-event/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=fmtp:101 0-15\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=sendrecv\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtcp:30437\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 192.168.11.140\r\n" /* <- NOTE: loses the 'o=' address, uses only 'c=' */</span><br><span style="color: hsl(120, 100%, 40%);">+          "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 192.168.11.140\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 30436 RTP/AVP 18 0 4 8 101\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtpmap:18 G729/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:0 PCMU/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:4 G723/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:8 PCMA/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:101 telephone-event/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=fmtp:101 0-15\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=ptime:20\r\n"</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%);">+void test_parse_and_compose()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        bool ok = true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("\n\n%s\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < ARRAY_SIZE(sdp_tests); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              struct sdp_test_data *t = &sdp_tests[i];</span><br><span style="color: hsl(120, 100%, 40%);">+          struct sdp_msg sdp = {};</span><br><span style="color: hsl(120, 100%, 40%);">+              char str[1024];</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("\n[%d]\n", i);</span><br><span style="color: hsl(120, 100%, 40%);">+              dump_sdp(t->sdp_input, "sdp input: ");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         sdp_msg_from_str(&sdp, t->sdp_input);</span><br><span style="color: hsl(120, 100%, 40%);">+          sdp_msg_to_str(str, sizeof(str), &sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         dump_sdp(str, "sdp_msg_to_str: ");</span><br><span style="color: hsl(120, 100%, 40%);">+          if (strcmp(str, t->expect_sdp_str)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      int j;</span><br><span style="color: hsl(120, 100%, 40%);">+                        ok = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                   printf("ERROR:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 dump_sdp(t->expect_sdp_str, "expect_sdp_str: ");</span><br><span style="color: hsl(120, 100%, 40%);">+                 for (j = 0; t->expect_sdp_str[j]; j++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           if (t->expect_sdp_str[j] != str[j]) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      printf("ERROR at position %d, at:\n", j);</span><br><span style="color: hsl(120, 100%, 40%);">+                                   dump_sdp(str + j, "     mismatch: ");</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%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        printf("[%d] ok\n", i);</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_ASSERT(ok);</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 sdp_intersect_test_data {</span><br><span style="color: hsl(120, 100%, 40%);">+       const char *descr;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *sdp_a;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *sdp_b;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *expect_intersection;</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 SDP_1 \</span><br><span style="color: hsl(120, 100%, 40%);">+               "v=0\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "s=GSM Call\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+          "c=IN IP4 23.42.23.42\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+                "t=0 0\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+               "m=audio 30436 RTP/AVP 112 3 111 110\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:112 AMR/8000\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=fmtp:112 octet-align=1\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtpmap:3 GSM/8000\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:111 GSM-HR-08/8000\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:110 GSM-EFR/8000\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define SDP_2 \</span><br><span style="color: hsl(120, 100%, 40%);">+         "v=0\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "s=GSM Call\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+          "c=IN IP4 23.42.23.42\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+                "t=0 0\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+               "m=audio 30436 RTP/AVP 112 110\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=rtpmap:112 AMR/8000\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=fmtp:112 octet-align=1\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtpmap:110 GSM-EFR/8000\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define SDP_3 \</span><br><span style="color: hsl(120, 100%, 40%);">+         "v=0\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "s=GSM Call\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+          "c=IN IP4 23.42.23.42\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+                "t=0 0\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+               "m=audio 30436 RTP/AVP 3 111\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:3 GSM/8000\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:111 GSM-HR-08/8000\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=ptime:20\r\n"</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 sdp_intersect_test_data sdp_intersect_tests[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      {</span><br><span style="color: hsl(120, 100%, 40%);">+             "identical codecs lead to no change"</span><br><span style="color: hsl(120, 100%, 40%);">+                ,</span><br><span style="color: hsl(120, 100%, 40%);">+             SDP_1</span><br><span style="color: hsl(120, 100%, 40%);">+         ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "c=IN IP4 5.6.7.8\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "m=audio 12345 RTP/AVP 112 3 111 110\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             ,</span><br><span style="color: hsl(120, 100%, 40%);">+             SDP_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%);">+             "identical codecs in different order also lead to no change"</span><br><span style="color: hsl(120, 100%, 40%);">+                ,</span><br><span style="color: hsl(120, 100%, 40%);">+             SDP_1</span><br><span style="color: hsl(120, 100%, 40%);">+         ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "c=IN IP4 5.6.7.8\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "m=audio 12345 RTP/AVP 3 110 111 112\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              ,</span><br><span style="color: hsl(120, 100%, 40%);">+             SDP_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%);">+             "identical codecs with mismatching payload type numbers also lead to no change"</span><br><span style="color: hsl(120, 100%, 40%);">+             ,</span><br><span style="color: hsl(120, 100%, 40%);">+             SDP_1</span><br><span style="color: hsl(120, 100%, 40%);">+         ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "c=IN IP4 5.6.7.8\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "m=audio 12345 RTP/AVP 96 97 98 99\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:96 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:97 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:98 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtpmap:99 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=fmtp:99 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               ,</span><br><span style="color: hsl(120, 100%, 40%);">+             SDP_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%);">+             "identical codecs plus some extra codecs also lead to no change"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             SDP_1</span><br><span style="color: hsl(120, 100%, 40%);">+         ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "c=IN IP4 5.6.7.8\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "m=audio 12345 RTP/AVP 8 0 96 97 98 99\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=rtpmap:8 PCMA/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:0 PCMU/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:96 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=rtpmap:97 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:98 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "a=rtpmap:99 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "a=fmtp:99 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+               ,</span><br><span style="color: hsl(120, 100%, 40%);">+             SDP_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%);">+             "some codecs removed",</span><br><span style="color: hsl(120, 100%, 40%);">+              SDP_1,</span><br><span style="color: hsl(120, 100%, 40%);">+                SDP_2,</span><br><span style="color: hsl(120, 100%, 40%);">+                SDP_2,</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%);">+             "other codecs removed",</span><br><span style="color: hsl(120, 100%, 40%);">+             SDP_1,</span><br><span style="color: hsl(120, 100%, 40%);">+                SDP_3,</span><br><span style="color: hsl(120, 100%, 40%);">+                SDP_3,</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%);">+             "all codecs removed",</span><br><span style="color: hsl(120, 100%, 40%);">+               SDP_1</span><br><span style="color: hsl(120, 100%, 40%);">+         ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "s=empty"</span><br><span style="color: hsl(120, 100%, 40%);">+           ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "v=0\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+         "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+            "s=GSM Call\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+          "c=IN IP4 23.42.23.42\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+                "t=0 0\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+               "m=audio 30436 RTP/AVP\r\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+               "a=ptime:20\r\n"</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%);">+             "some real world test case"</span><br><span style="color: hsl(120, 100%, 40%);">+         ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 0.0.0.0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 0.0.0.0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 0 RTP/AVP 112 113 110 3 111\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1;mode-set=0,1,2,3\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:113 AMR-WB/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=fmtp:113 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 0.0.0.0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 0.0.0.0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 0 RTP/AVP 112 113 110 3 111\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1;mode-set=0,1,2,3\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:113 AMR-WB/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=fmtp:113 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 0.0.0.0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 0.0.0.0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 0 RTP/AVP 112 113 110 3 111\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1;mode-set=0,1,2,3\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:113 AMR-WB/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=fmtp:113 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=ptime:20\r\n"</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 char *sdp_msg_logstr(const struct sdp_msg *sdp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     static char buf[1024];</span><br><span style="color: hsl(120, 100%, 40%);">+        sdp_msg_to_str(buf, sizeof(buf), sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+        return buf;</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 void test_intersect()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        bool ok = true;</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%);">+     printf("\n\n%s\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < ARRAY_SIZE(sdp_intersect_tests); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            struct sdp_intersect_test_data *t = &sdp_intersect_tests[i];</span><br><span style="color: hsl(120, 100%, 40%);">+              struct sdp_msg sdp_a = {};</span><br><span style="color: hsl(120, 100%, 40%);">+            struct sdp_msg sdp_b = {};</span><br><span style="color: hsl(120, 100%, 40%);">+            char str[1024];</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("\n[%d] %s\n", i, t->descr);</span><br><span style="color: hsl(120, 100%, 40%);">+              dump_sdp(t->sdp_a, "SDP A: ");</span><br><span style="color: hsl(120, 100%, 40%);">+           dump_sdp(t->sdp_b, " SDP B: ");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                rc = sdp_msg_from_str(&sdp_a, t->sdp_a);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("ERROR parsing SDP A: %d\n", rc);</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%);">+             dump_sdp(sdp_msg_logstr(&sdp_a), "parsed SDP A: ");</span><br><span style="color: hsl(120, 100%, 40%);">+             rc = sdp_msg_from_str(&sdp_b, t->sdp_b);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("ERROR parsing SDP A: %d\n", rc);</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%);">+             dump_sdp(sdp_msg_logstr(&sdp_b), "parsed SDP B: ");</span><br><span style="color: hsl(120, 100%, 40%);">+             sdp_audio_codecs_intersection(&sdp_a.audio_codecs, &sdp_b.audio_codecs, false);</span><br><span style="color: hsl(120, 100%, 40%);">+               sdp_msg_to_str(str, sizeof(str), &sdp_a);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               dump_sdp(str, "sdp_msg_intersection(a,b): ");</span><br><span style="color: hsl(120, 100%, 40%);">+               if (strcmp(str, t->expect_intersection)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 int j;</span><br><span style="color: hsl(120, 100%, 40%);">+                        ok = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                   printf("ERROR:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 dump_sdp(t->expect_intersection, "expect_intersection: ");</span><br><span style="color: hsl(120, 100%, 40%);">+                       for (j = 0; t->expect_intersection[j]; j++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              if (t->expect_intersection[j] != str[j]) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                 printf("ERROR at position %d, at:\n", j);</span><br><span style="color: hsl(120, 100%, 40%);">+                                   dump_sdp(str + j, "     mismatch: ");</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%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        printf("[%d] ok\n", i);</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_ASSERT(ok);</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 sdp_select_test_data {</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *sdp;</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned int select_payload_type;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *expect_sdp;</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 sdp_select_test_data sdp_select_tests[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     {</span><br><span style="color: hsl(120, 100%, 40%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 30436 RTP/AVP 112 3 111 110\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             112,</span><br><span style="color: hsl(120, 100%, 40%);">+          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%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 30436 RTP/AVP 112 3 111 110\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             3,</span><br><span style="color: hsl(120, 100%, 40%);">+            "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 30436 RTP/AVP 3 112 111 110\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=ptime:20\r\n"</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%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 30436 RTP/AVP 112 3 111 110\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             111,</span><br><span style="color: hsl(120, 100%, 40%);">+          "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 30436 RTP/AVP 111 112 3 110\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=ptime:20\r\n"</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%);">+             "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 30436 RTP/AVP 112 3 111 110\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=ptime:20\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            ,</span><br><span style="color: hsl(120, 100%, 40%);">+             110,</span><br><span style="color: hsl(120, 100%, 40%);">+          "v=0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "s=GSM Call\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+            "c=IN IP4 23.42.23.42\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+          "t=0 0\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "m=audio 30436 RTP/AVP 110 112 3 111\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:110 GSM-EFR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+             "a=rtpmap:112 AMR/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+         "a=fmtp:112 octet-align=1\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+              "a=rtpmap:3 GSM/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=rtpmap:111 GSM-HR-08/8000\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+           "a=ptime:20\r\n"</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%);">+static void test_select()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        bool ok = true;</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%);">+     printf("\n\n%s\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < ARRAY_SIZE(sdp_select_tests); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct sdp_select_test_data *t = &sdp_select_tests[i];</span><br><span style="color: hsl(120, 100%, 40%);">+            struct sdp_msg sdp = {};</span><br><span style="color: hsl(120, 100%, 40%);">+              struct sdp_audio_codec *codec;</span><br><span style="color: hsl(120, 100%, 40%);">+                char buf[1024];</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("\n[%d]\n", i);</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = sdp_msg_from_str(&sdp, t->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("ERROR parsing SDP: %d\n", rc);</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%);">+             printf("SDP: %s\n", sdp_audio_codecs_name(&sdp.audio_codecs));</span><br><span style="color: hsl(120, 100%, 40%);">+          codec = sdp_audio_codec_by_payload_type(&sdp.audio_codecs, t->select_payload_type, false);</span><br><span style="color: hsl(120, 100%, 40%);">+             OSMO_ASSERT(codec);</span><br><span style="color: hsl(120, 100%, 40%);">+           printf("Select: %s\n", sdp_audio_codec_name(codec));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              sdp_audio_codecs_select(&sdp.audio_codecs, codec);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              printf("SDP: %s\n", sdp_audio_codecs_name(&sdp.audio_codecs));</span><br><span style="color: hsl(120, 100%, 40%);">+          sdp_msg_to_str(buf, sizeof(buf), &sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         if (strcmp(buf, t->expect_sdp ? : t->sdp)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    int j;</span><br><span style="color: hsl(120, 100%, 40%);">+                        ok = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                   printf("ERROR:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 dump_sdp(buf, "selection result: ");</span><br><span style="color: hsl(120, 100%, 40%);">+                        dump_sdp(t->expect_sdp, "expect result: ");</span><br><span style="color: hsl(120, 100%, 40%);">+                      for (j = 0; t->expect_sdp[j]; j++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               if (t->expect_sdp[j] != buf[j]) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                  printf("ERROR at position %d, at:\n", j);</span><br><span style="color: hsl(120, 100%, 40%);">+                                   dump_sdp(buf + j, "     mismatch: ");</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%);">+             } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        printf("[%d] ok\n", i);</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_ASSERT(ok);</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(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      test_parse_and_compose();</span><br><span style="color: hsl(120, 100%, 40%);">+     test_intersect();</span><br><span style="color: hsl(120, 100%, 40%);">+     test_select();</span><br><span style="color: hsl(120, 100%, 40%);">+        return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/tests/sdp_msg/sdp_msg_test.err b/tests/sdp_msg/sdp_msg_test.err</span><br><span>new file mode 100644</span><br><span>index 0000000..e69de29</span><br><span>--- /dev/null</span><br><span>+++ b/tests/sdp_msg/sdp_msg_test.err</span><br><span>diff --git a/tests/sdp_msg/sdp_msg_test.ok b/tests/sdp_msg/sdp_msg_test.ok</span><br><span>new file mode 100644</span><br><span>index 0000000..a7a3d51</span><br><span>--- /dev/null</span><br><span>+++ b/tests/sdp_msg/sdp_msg_test.ok</span><br><span>@@ -0,0 +1,590 @@</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%);">+test_parse_and_compose</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[0]</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: o=- 5628250 5628250 IN IP4 192.168.11.121\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: s=-\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: c=IN IP4 192.168.11.121\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: m=audio 10020 RTP/AVP 18 0 2 4 8 96 97 98 100 101\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:18 G729/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:0 PCMU/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:2 G726-32/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:4 G723/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:8 PCMA/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:96 G726-40/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:97 G726-24/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:98 G726-16/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:100 NSE/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=fmtp:100 192-193\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:101 telephone-event/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=fmtp:101 0-15\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=sendrecv\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: o=OsmoMSC 0 0 IN IP4 192.168.11.121\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: c=IN IP4 192.168.11.121\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: m=audio 10020 RTP/AVP 18 0 2 4 8 96 97 98 100 101\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:18 G729/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:0 PCMU/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:2 G726-32/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:4 G723/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:8 PCMA/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:96 G726-40/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:97 G726-24/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:98 G726-16/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:100 NSE/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=fmtp:100 192-193\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:101 telephone-event/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=fmtp:101 0-15\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[0] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[1]</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: o=FooBar 1565090289 1565090290 IN IP4 192.168.11.151\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: s=FooBar\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: c=IN IP4 192.168.11.151\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: m=audio 16398 RTP/AVP 98\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:98 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=fmtp:98 octet-align=1; mode-set=4\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtcp:16399 IN IP4 192.168.11.151\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: o=OsmoMSC 0 0 IN IP4 192.168.11.151\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: c=IN IP4 192.168.11.151\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: m=audio 16398 RTP/AVP 98\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:98 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=fmtp:98 octet-align=1; mode-set=4\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[1] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[2]</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: o=FooBar 1565090289 1565090290 IN IP4 192.168.11.151\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: s=FooBar\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: c=IN IP4 192.168.11.140\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: m=audio 30436 RTP/AVP 18 0 4 8 101\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:18 G729/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:0 PCMU/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:4 G723/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:8 PCMA/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtpmap:101 telephone-event/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=fmtp:101 0-15\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=sendrecv\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=rtcp:30437\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp input: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: o=OsmoMSC 0 0 IN IP4 192.168.11.140\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: c=IN IP4 192.168.11.140\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: m=audio 30436 RTP/AVP 18 0 4 8 101\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:18 G729/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:0 PCMU/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:4 G723/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:8 PCMA/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=rtpmap:101 telephone-event/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=fmtp:101 0-15\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_to_str: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[2] ok</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%);">+test_intersect</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[0] identical codecs lead to no change</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: c=IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: m=audio 12345 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: o=OsmoMSC 0 0 IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: c=IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: m=audio 12345 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[0] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[1] identical codecs in different order also lead to no change</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: c=IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: m=audio 12345 RTP/AVP 3 110 111 112\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: o=OsmoMSC 0 0 IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: c=IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: m=audio 12345 RTP/AVP 3 110 111 112\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[1] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[2] identical codecs with mismatching payload type numbers also lead to no change</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: c=IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: m=audio 12345 RTP/AVP 96 97 98 99\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:96 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:97 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:98 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:99 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=fmtp:99 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: o=OsmoMSC 0 0 IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: c=IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: m=audio 12345 RTP/AVP 96 97 98 99\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:96 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:97 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:98 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:99 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=fmtp:99 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[2] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[3] identical codecs plus some extra codecs also lead to no change</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: c=IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: m=audio 12345 RTP/AVP 8 0 96 97 98 99\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:8 PCMA/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:0 PCMU/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:96 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:97 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:98 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:99 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=fmtp:99 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: o=OsmoMSC 0 0 IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: c=IN IP4 5.6.7.8\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: m=audio 12345 RTP/AVP 8 0 96 97 98 99\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:8 PCMA/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:0 PCMU/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:96 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:97 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:98 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:99 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=fmtp:99 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[3] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[4] some codecs removed</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: m=audio 30436 RTP/AVP 112 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: m=audio 30436 RTP/AVP 112 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): m=audio 30436 RTP/AVP 112 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[4] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[5] other codecs removed</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: m=audio 30436 RTP/AVP 3 111\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: m=audio 30436 RTP/AVP 3 111\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): m=audio 30436 RTP/AVP 3 111\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[5] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[6] all codecs removed</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: s=empty</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: m=audio 30436 RTP/AVP 112 3 111 110\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=fmtp:112 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: o=OsmoMSC 0 0 IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: c=IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: m=audio 0 RTP/AVP\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): o=OsmoMSC 0 0 IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): c=IN IP4 23.42.23.42\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): m=audio 30436 RTP/AVP\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[6] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[7] some real world test case</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: o=OsmoMSC 0 0 IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: c=IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: m=audio 0 RTP/AVP 112 113 110 3 111\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=fmtp:112 octet-align=1;mode-set=0,1,2,3\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:113 AMR-WB/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=fmtp:113 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: o=OsmoMSC 0 0 IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: c=IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: m=audio 0 RTP/AVP 112 113 110 3 111\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=fmtp:112 octet-align=1;mode-set=0,1,2,3\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:113 AMR-WB/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=fmtp:113 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+ SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: o=OsmoMSC 0 0 IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: c=IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: m=audio 0 RTP/AVP 112 113 110 3 111\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=fmtp:112 octet-align=1;mode-set=0,1,2,3\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:113 AMR-WB/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=fmtp:113 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP A: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: o=OsmoMSC 0 0 IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: c=IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: m=audio 0 RTP/AVP 112 113 110 3 111\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=fmtp:112 octet-align=1;mode-set=0,1,2,3\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:113 AMR-WB/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=fmtp:113 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+parsed SDP B: a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): v=0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): o=OsmoMSC 0 0 IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): s=GSM Call\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): c=IN IP4 0.0.0.0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): t=0 0\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): m=audio 0 RTP/AVP 112 113 110 3 111\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:112 AMR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=fmtp:112 octet-align=1;mode-set=0,1,2,3\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:113 AMR-WB/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=fmtp:113 octet-align=1\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:110 GSM-EFR/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:3 GSM/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=rtpmap:111 GSM-HR-08/8000\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+sdp_msg_intersection(a,b): a=ptime:20\r\n</span><br><span style="color: hsl(120, 100%, 40%);">+[7] ok</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%);">+test_select</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[0]</span><br><span style="color: hsl(120, 100%, 40%);">+SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR</span><br><span style="color: hsl(120, 100%, 40%);">+Select: AMR:octet-align=1</span><br><span style="color: hsl(120, 100%, 40%);">+SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR</span><br><span style="color: hsl(120, 100%, 40%);">+[0] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[1]</span><br><span style="color: hsl(120, 100%, 40%);">+SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR</span><br><span style="color: hsl(120, 100%, 40%);">+Select: GSM</span><br><span style="color: hsl(120, 100%, 40%);">+SDP: GSM,AMR:octet-align=1,GSM-HR-08,GSM-EFR</span><br><span style="color: hsl(120, 100%, 40%);">+[1] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[2]</span><br><span style="color: hsl(120, 100%, 40%);">+SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR</span><br><span style="color: hsl(120, 100%, 40%);">+Select: GSM-HR-08</span><br><span style="color: hsl(120, 100%, 40%);">+SDP: GSM-HR-08,AMR:octet-align=1,GSM,GSM-EFR</span><br><span style="color: hsl(120, 100%, 40%);">+[2] ok</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[3]</span><br><span style="color: hsl(120, 100%, 40%);">+SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR</span><br><span style="color: hsl(120, 100%, 40%);">+Select: GSM-EFR</span><br><span style="color: hsl(120, 100%, 40%);">+SDP: GSM-EFR,AMR:octet-align=1,GSM,GSM-HR-08</span><br><span style="color: hsl(120, 100%, 40%);">+[3] ok</span><br><span>diff --git a/tests/testsuite.at b/tests/testsuite.at</span><br><span>index c0788b9..946d0db 100644</span><br><span>--- a/tests/testsuite.at</span><br><span>+++ b/tests/testsuite.at</span><br><span>@@ -107,3 +107,10 @@</span><br><span> cat $abs_srcdir/msc_vlr/msc_vlr_test_ss.err > experr</span><br><span> AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_ss], [], [expout], [experr])</span><br><span> AT_CLEANUP</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AT_SETUP([sdp_msg_test])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_KEYWORDS([sdp_msg_test])</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/sdp_msg/sdp_msg_test.ok > expout</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/sdp_msg/sdp_msg_test.err > experr</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CHECK([$abs_top_builddir/tests/sdp_msg/sdp_msg_test], [], [expout], [experr])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CLEANUP</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-msc/+/15947">change 15947</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/osmo-msc/+/15947"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-msc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: If3ce23cd5bab15e2ab4c52ef3e4c75979dffe931 </div>
<div style="display:none"> Gerrit-Change-Number: 15947 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>