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