<p>Vadim Yanitskiy has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/10034">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Introduce info / features negotiation helper functions<br><br>In some projects, such as OsmocomBB and SIMTrace, where the host<br>software needs to communicate with different HW / SW back-ends<br>(e.g. OsmocomBB/mobile and Calypso firmware), it is important<br>to have a possibility to negotiate some information between<br>the both sides, for example, a list of supported features,<br>or some meta-information about a hardware back-end.<br><br>This change introduces the new API exactly for that, and can<br>be used in order to avoid code duplication, and implementing<br>the wheel again and again.<br><br>At the moment, there are two kinds of information that can be<br>negotiated:<br><br>  - TLV-based text chunks,<br>  - feature flags.<br><br>First kind of info can be used to describe some meta-information,<br>for example, HW board name, FW or SW version. Also, it can be<br>used to describe some non-binary properties, for example,<br>a preferred TCH frame format.<br><br>The feature flags can be used to indicate that one or more<br>features from a set shared between the both sides is/are<br>supported. If particular flag is preset in the encoded<br>message, the associated feature is supported, otherwise<br>it is not supported, or not implemented.<br><br>Basic usage examples can be found in implementation<br>of the unit test: tests/nego/nego_test.c.<br><br>Change-Id: I6fd5b6be6755d4aa735a510e95459180225389ba<br>---<br>M include/Makefile.am<br>A include/osmocom/core/negotiation.h<br>M src/Makefile.am<br>A src/negotiation.c<br>M tests/Makefile.am<br>A tests/nego/nego_test.c<br>A tests/nego/nego_test.ok<br>M tests/testsuite.at<br>8 files changed, 428 insertions(+), 3 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/34/10034/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/Makefile.am b/include/Makefile.am</span><br><span>index 38ba14c..158a1b8 100644</span><br><span>--- a/include/Makefile.am</span><br><span>+++ b/include/Makefile.am</span><br><span>@@ -51,6 +51,7 @@</span><br><span>                        osmocom/core/timer_compat.h \</span><br><span>                        osmocom/core/utils.h \</span><br><span>                        osmocom/core/write_queue.h \</span><br><span style="color: hsl(120, 100%, 40%);">+                       osmocom/core/negotiation.h \</span><br><span>                        osmocom/crypt/auth.h \</span><br><span>                        osmocom/crypt/gprs_cipher.h \</span><br><span>                      osmocom/ctrl/control_cmd.h \</span><br><span>diff --git a/include/osmocom/core/negotiation.h b/include/osmocom/core/negotiation.h</span><br><span>new file mode 100644</span><br><span>index 0000000..86096f0</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/core/negotiation.h</span><br><span>@@ -0,0 +1,13 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.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/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_nego_enc_info(struct msgb *msg, const struct value_string *info);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_nego_get_info(const uint8_t *buf, size_t buf_len, uint8_t info_tag);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_nego_add_feature(struct msgb *msg, uint8_t feature);</span><br><span style="color: hsl(120, 100%, 40%);">+bool osmo_nego_check_feature(const uint8_t *buf, size_t buf_len, uint8_t feature);</span><br><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index 45fb89d..91cdefb 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -23,7 +23,7 @@</span><br><span>                        loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c \</span><br><span>                     macaddr.c stat_item.c stats.c stats_statsd.c prim.c \</span><br><span>                        conv_acc.c conv_acc_generic.c sercomm.c prbs.c \</span><br><span style="color: hsl(0, 100%, 40%);">-                        isdnhdlc.c</span><br><span style="color: hsl(120, 100%, 40%);">+                    isdnhdlc.c negotiation.c</span><br><span> </span><br><span> if HAVE_SSSE3</span><br><span> libosmocore_la_SOURCES += conv_acc_sse.c</span><br><span>diff --git a/src/negotiation.c b/src/negotiation.c</span><br><span>new file mode 100644</span><br><span>index 0000000..5aa5d34</span><br><span>--- /dev/null</span><br><span>+++ b/src/negotiation.c</span><br><span>@@ -0,0 +1,138 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file negotiation.c</span><br><span style="color: hsl(120, 100%, 40%);">+ * Helper functions for info / feature negotiation. */</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.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/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/tlv.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Encode given list of information into a TLV-based message buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  The given list of information is represented by \ref value_string</span><br><span style="color: hsl(120, 100%, 40%);">+ *  structure, where value defines a kind of information (e.g. firmware</span><br><span style="color: hsl(120, 100%, 40%);">+ *  version, board name), and string in its turn defines the information</span><br><span style="color: hsl(120, 100%, 40%);">+ *  itself (e.g. '0.8.1.28-91e7b', 'AT91SAM7S').</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Limitations: Tag and Length values occupy one byte each, so it's</span><br><span style="color: hsl(120, 100%, 40%);">+ *  possible to encode up to 256 unique information chunks, up to</span><br><span style="color: hsl(120, 100%, 40%);">+ *  256 bytes long each. This should be enough for the most cases.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Exceeding T and V values are not permitted.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Note: strings are encoded with '\0'!</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] msg caller allocated message buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] info list of information to be encoded</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns        how many info chunks were encoded</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_nego_enc_info(struct msgb *msg, const struct value_string *info)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     size_t len;</span><br><span style="color: hsl(120, 100%, 40%);">+   int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Iterate over a given info list */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0;; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (info[i].value == 0 && info[i].str == NULL)</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%);">+              /* Encoding limitations */</span><br><span style="color: hsl(120, 100%, 40%);">+            OSMO_ASSERT(info[i].value <= 0xff);</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_ASSERT(info[i].str != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Strings are encoded with '\0' */</span><br><span style="color: hsl(120, 100%, 40%);">+           len = strlen(info[i].str) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_ASSERT(len <= 0xff);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                msgb_tlv_put(msg, info[i].value, len,</span><br><span style="color: hsl(120, 100%, 40%);">+                 (const uint8_t *) info[i].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 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%);">+/*! Get info chunk corresponding to a given tag</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] buf      TLV-encoded buffer to be parsed</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] buf_len  TLV-encoded buffer length</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] info_tag tag of required info</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns            pointer to info string or NULL</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_nego_get_info(const uint8_t *buf, size_t buf_len, uint8_t info_tag)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   const uint8_t *pos = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t tag, len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while ((pos + 2) < (buf + buf_len)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              tag = pos[0];</span><br><span style="color: hsl(120, 100%, 40%);">+         len = pos[1];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Prevent string out of bounds */</span><br><span style="color: hsl(120, 100%, 40%);">+            if ((pos + 2 + len) > (buf + buf_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%);">+              /* Match info tag */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (tag == info_tag)</span><br><span style="color: hsl(120, 100%, 40%);">+                  return (char *)(pos + 2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Seek the pointer */</span><br><span style="color: hsl(120, 100%, 40%);">+                pos += len + 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%);">+   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%);">+/*! Append a new feature to a given list of features</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Limitations: up to 256 features can be encoded.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] msg    caller allocated message buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] feature a new feature to be added</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_nego_add_feature(struct msgb *msg, uint8_t feature)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *byte = msgb_put(msg, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+     *byte = feature;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Append a new feature to a given list of features</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] buf      feature list to be parsed</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] buf_len  feature list length</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] feature  the feature to be checked</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns            true if the feature is preset,</span><br><span style="color: hsl(120, 100%, 40%);">+ *                      false otherwise</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+bool osmo_nego_check_feature(const uint8_t *buf, size_t buf_len, uint8_t feature)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        size_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < buf_len; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+              if (buf[i] == feature)</span><br><span style="color: hsl(120, 100%, 40%);">+                        return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return false;</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 db4e520..9e75dcf 100644</span><br><span>--- a/tests/Makefile.am</span><br><span>+++ b/tests/Makefile.am</span><br><span>@@ -23,7 +23,8 @@</span><br><span>                 coding/coding_test conv/conv_gsm0503_test              \</span><br><span>             abis/abis_test endian/endian_test sercomm/sercomm_test \</span><br><span>             prbs/prbs_test gsm23003/gsm23003_test                  \</span><br><span style="color: hsl(0, 100%, 40%);">-                codec/codec_ecu_fr_test timer/clk_override_test</span><br><span style="color: hsl(120, 100%, 40%);">+               codec/codec_ecu_fr_test timer/clk_override_test        \</span><br><span style="color: hsl(120, 100%, 40%);">+              nego/nego_test</span><br><span> </span><br><span> if ENABLE_MSGFILE</span><br><span> check_PROGRAMS += msgfile/msgfile_test</span><br><span>@@ -194,6 +195,9 @@</span><br><span> gsm23003_gsm23003_test_SOURCES = gsm23003/gsm23003_test.c</span><br><span> gsm23003_gsm23003_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+nego_nego_test_SOURCES = nego/nego_test.c</span><br><span style="color: hsl(120, 100%, 40%);">+nego_nego_test_LDADD = $(LDADD)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # The `:;' works around a Bash 3.2 bug when the output is not writeable.</span><br><span> $(srcdir)/package.m4: $(top_srcdir)/configure.ac</span><br><span>         :;{ \</span><br><span>@@ -253,7 +257,7 @@</span><br><span>       conv/conv_gsm0503_test.ok endian/endian_test.ok            \</span><br><span>         sercomm/sercomm_test.ok prbs/prbs_test.ok                  \</span><br><span>         gsm23003/gsm23003_test.ok                                 \</span><br><span style="color: hsl(0, 100%, 40%);">-             timer/clk_override_test.ok</span><br><span style="color: hsl(120, 100%, 40%);">+            timer/clk_override_test.ok nego/nego_test.ok</span><br><span> </span><br><span> DISTCLEANFILES = atconfig atlocal conv/gsm0503_test_vectors.c</span><br><span> BUILT_SOURCES = conv/gsm0503_test_vectors.c</span><br><span>diff --git a/tests/nego/nego_test.c b/tests/nego/nego_test.c</span><br><span>new file mode 100644</span><br><span>index 0000000..ec19f16</span><br><span>--- /dev/null</span><br><span>+++ b/tests/nego/nego_test.c</span><br><span>@@ -0,0 +1,170 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/negotiation.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define NEGO_MSGB_SIZE 256</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum nego_test_feature_tag {</span><br><span style="color: hsl(120, 100%, 40%);">+       NEGO_TEST_FEATURE_F0 = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+     NEGO_TEST_FEATURE_F1,</span><br><span style="color: hsl(120, 100%, 40%);">+ NEGO_TEST_FEATURE_F2,</span><br><span style="color: hsl(120, 100%, 40%);">+ NEGO_TEST_FEATURE_F3,</span><br><span style="color: hsl(120, 100%, 40%);">+ NEGO_TEST_FEATURE_F4,</span><br><span style="color: hsl(120, 100%, 40%);">+ NEGO_TEST_FEATURE_F5,</span><br><span style="color: hsl(120, 100%, 40%);">+ _NEGO_TEST_FEATURE_MAX</span><br><span 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 nego_test_features(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+     bool check;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("[T] Testing negotiation of features...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       msg = msgb_alloc(NEGO_MSGB_SIZE, "nego_features");</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   printf("[i] Encoding a few features\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_nego_add_feature(msg, NEGO_TEST_FEATURE_F2);</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_nego_add_feature(msg, NEGO_TEST_FEATURE_F5);</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("[?] Message: %s\n", msgb_hexdump(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   printf("[i] Verifying recently encoded features...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+     check = osmo_nego_check_feature(msg->data,</span><br><span style="color: hsl(120, 100%, 40%);">+         msgb_length(msg), NEGO_TEST_FEATURE_F2);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(check);</span><br><span style="color: hsl(120, 100%, 40%);">+   check = osmo_nego_check_feature(msg->data,</span><br><span style="color: hsl(120, 100%, 40%);">+         msgb_length(msg), NEGO_TEST_FEATURE_F5);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(check);</span><br><span style="color: hsl(120, 100%, 40%);">+   printf("[+] Expected features preset\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("[i] Verifying non-existing features...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ check = osmo_nego_check_feature(msg->data,</span><br><span style="color: hsl(120, 100%, 40%);">+         msgb_length(msg), NEGO_TEST_FEATURE_F1);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(!check);</span><br><span style="color: hsl(120, 100%, 40%);">+  check = osmo_nego_check_feature(msg->data,</span><br><span style="color: hsl(120, 100%, 40%);">+         msgb_length(msg), NEGO_TEST_FEATURE_F3);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(!check);</span><br><span style="color: hsl(120, 100%, 40%);">+  check = osmo_nego_check_feature(msg->data,</span><br><span style="color: hsl(120, 100%, 40%);">+         msgb_length(msg), NEGO_TEST_FEATURE_F4);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(!check);</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[+] Unexpected features not preset\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   printf("[i] Adding some more features...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_nego_add_feature(msg, NEGO_TEST_FEATURE_F1);</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_nego_add_feature(msg, NEGO_TEST_FEATURE_F3);</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("[?] Message: %s\n", msgb_hexdump(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("\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%);">+enum nego_test_info_tag {</span><br><span style="color: hsl(120, 100%, 40%);">+       NEGO_TEST_INFO_PROP0 = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+     NEGO_TEST_INFO_PROP1,</span><br><span style="color: hsl(120, 100%, 40%);">+ NEGO_TEST_INFO_PROP2,</span><br><span style="color: hsl(120, 100%, 40%);">+ NEGO_TEST_INFO_PROP3,</span><br><span style="color: hsl(120, 100%, 40%);">+ _NEGO_TEST_INFO_MAX</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct value_string info_list[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_VALUE_STRING(NEGO_TEST_INFO_PROP0),</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_VALUE_STRING(NEGO_TEST_INFO_PROP1),</span><br><span style="color: hsl(120, 100%, 40%);">+      /* NEGO_TEST_INFO_PROP2 is intentionally not included */</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_VALUE_STRING(NEGO_TEST_INFO_PROP3),</span><br><span style="color: hsl(120, 100%, 40%);">+      { 0, 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%);">+int dump_encoded_info(struct msgb *msg, bool print_info)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *info_str;</span><br><span style="color: hsl(120, 100%, 40%);">+ int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t tag;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        for (tag = 0; tag < _NEGO_TEST_INFO_MAX; tag++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          info_str = osmo_nego_get_info(msg->data, msgb_length(msg), tag);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!info_str)</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%);">+           if (print_info)</span><br><span style="color: hsl(120, 100%, 40%);">+                       printf("[?] Decoded info: tag 0x%02x, value '%s'\n", tag, info_str);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              count++;</span><br><span 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 count;</span><br><span 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 nego_test_info(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *info_str;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+     int rc, len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("[T] Testing info negotiation...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      msg = msgb_alloc(NEGO_MSGB_SIZE, "nego_info");</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   printf("[i] Encoding info list...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      rc = osmo_nego_enc_info(msg, info_list);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(rc > 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("[?] Encoded %d chunks\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("[?] Message: %s\n", msgb_hexdump(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   printf("[i] Checking encoded info...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+   dump_encoded_info(msg, true);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("[i] Trying to get missing info...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      info_str = osmo_nego_get_info(msg->data,</span><br><span style="color: hsl(120, 100%, 40%);">+           msgb_length(msg), NEGO_TEST_INFO_PROP2);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(info_str == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("[+] Unexpected info not preset\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("[i] Checking buffer limiting...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        len = msgb_length(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+       do {</span><br><span style="color: hsl(120, 100%, 40%);">+          msgb_trim(msg, len);</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = dump_encoded_info(msg, false);</span><br><span style="color: hsl(120, 100%, 40%);">+           printf("[?] Buffer len=%d, decoded=%d\n", len, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ } while (--len >= 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("\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%);">+int main(int argc, char **argv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      void *ctx = talloc_init("nego_test");</span><br><span style="color: hsl(120, 100%, 40%);">+       msgb_talloc_ctx_init(ctx, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       nego_test_features();</span><br><span style="color: hsl(120, 100%, 40%);">+ nego_test_info();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   printf("[i] Success!\n");</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/nego/nego_test.ok b/tests/nego/nego_test.ok</span><br><span>new file mode 100644</span><br><span>index 0000000..285b089</span><br><span>--- /dev/null</span><br><span>+++ b/tests/nego/nego_test.ok</span><br><span>@@ -0,0 +1,93 @@</span><br><span style="color: hsl(120, 100%, 40%);">+[T] Testing negotiation of features...</span><br><span style="color: hsl(120, 100%, 40%);">+[i] Encoding a few features</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Message: 02 05 </span><br><span style="color: hsl(120, 100%, 40%);">+[i] Verifying recently encoded features...</span><br><span style="color: hsl(120, 100%, 40%);">+[+] Expected features preset</span><br><span style="color: hsl(120, 100%, 40%);">+[i] Verifying non-existing features...</span><br><span style="color: hsl(120, 100%, 40%);">+[+] Unexpected features not preset</span><br><span style="color: hsl(120, 100%, 40%);">+[i] Adding some more features...</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Message: 02 05 01 03 </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[T] Testing info negotiation...</span><br><span style="color: hsl(120, 100%, 40%);">+[i] Encoding info list...</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Encoded 3 chunks</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Message: 00 15 4e 45 47 4f 5f 54 45 53 54 5f 49 4e 46 4f 5f 50 52 4f 50 30 00 01 15 4e 45 47 4f 5f 54 45 53 54 5f 49 4e 46 4f 5f 50 52 4f 50 31 00 03 15 4e 45 47 4f 5f 54 45 53 54 5f 49 4e 46 4f 5f 50 52 4f 50 33 00 </span><br><span style="color: hsl(120, 100%, 40%);">+[i] Checking encoded info...</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Decoded info: tag 0x00, value 'NEGO_TEST_INFO_PROP0'</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Decoded info: tag 0x01, value 'NEGO_TEST_INFO_PROP1'</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Decoded info: tag 0x03, value 'NEGO_TEST_INFO_PROP3'</span><br><span style="color: hsl(120, 100%, 40%);">+[i] Trying to get missing info...</span><br><span style="color: hsl(120, 100%, 40%);">+[+] Unexpected info not preset</span><br><span style="color: hsl(120, 100%, 40%);">+[i] Checking buffer limiting...</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=69, decoded=3</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=68, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=67, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=66, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=65, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=64, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=63, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=62, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=61, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=60, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=59, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=58, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=57, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=56, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=55, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=54, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=53, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=52, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=51, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=50, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=49, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=48, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=47, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=46, decoded=2</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=45, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=44, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=43, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=42, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=41, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=40, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=39, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=38, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=37, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=36, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=35, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=34, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=33, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=32, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=31, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=30, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=29, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=28, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=27, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=26, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=25, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=24, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=23, decoded=1</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=22, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=21, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=20, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=19, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=18, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=17, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=16, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=15, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=14, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=13, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=12, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=11, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=10, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=9, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=8, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=7, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=6, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=5, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=4, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=3, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=2, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=1, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+[?] Buffer len=0, decoded=0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[i] Success!</span><br><span>diff --git a/tests/testsuite.at b/tests/testsuite.at</span><br><span>index 15a89b6..5ab3373 100644</span><br><span>--- a/tests/testsuite.at</span><br><span>+++ b/tests/testsuite.at</span><br><span>@@ -311,3 +311,9 @@</span><br><span> cat $abs_srcdir/gsm23003/gsm23003_test.ok > expout</span><br><span> AT_CHECK([$abs_top_builddir/tests/gsm23003/gsm23003_test], [0], [expout], [ignore])</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([nego])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_KEYWORDS([nego])</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/nego/nego_test.ok > expout</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CHECK([$abs_top_builddir/tests/nego/nego_test], [0], [expout], [ignore])</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/10034">change 10034</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/10034"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I6fd5b6be6755d4aa735a510e95459180225389ba </div>
<div style="display:none"> Gerrit-Change-Number: 10034 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Vadim Yanitskiy <axilirator@gmail.com> </div>