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