This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
dexter gerrit-no-reply at lists.osmocom.org
Review at https://gerrit.osmocom.org/2177
gsm0808: Add utils for Speech Codec List and Speech Codec
The planned support for true A over IP requires the encoding and
decoding of a so called "Speech Codec Element" element.
This commt adds parsing functionality and tests for the element
mentioned above, however, it is not yet actively used.
Change-Id: I0e1e2edf47adaa45b22d4b0bcae3640dba7ca200
---
M include/osmocom/gsm/gsm0808_utils.h
M include/osmocom/gsm/protocol/gsm_08_08.h
M src/gsm/gsm0808_utils.c
M src/gsm/libosmogsm.map
M tests/gsm0808/gsm0808_test.c
5 files changed, 367 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/77/2177/1
diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index d4d8618..4049a2f 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -21,9 +21,25 @@
#include <sys/socket.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
+
/* Encode AoIP transport address element */
struct msgb *gsm0808_enc_aoip_trasp_addr(struct sockaddr_storage *ss);
/* Decode AoIP transport address element */
struct sockaddr_storage *gsm0808_dec_aoip_trasp_addr(const void *ctx,
struct msgb *msg);
+
+/* Encode Speech Codec element */
+struct msgb *gsm0808_enc_speech_codec(struct gsm0808_speech_codec *sc);
+
+/* Decode Speech Codec element */
+struct gsm0808_speech_codec *gsm0808_dec_speech_codec(const void *ctx,
+ struct msgb *msg);
+
+/* Encode Speech Codec list */
+struct msgb *gsm0808_enc_speech_codec_list(struct llist_head *scl);
+
+/* Decode Speech Codec list */
+struct llist_head *gsm0808_dec_speech_codec_list(const void *ctx,
+ struct msgb *msg);
diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h
index 6fb4e9e..ad5e633 100644
--- a/include/osmocom/gsm/protocol/gsm_08_08.h
+++ b/include/osmocom/gsm/protocol/gsm_08_08.h
@@ -3,6 +3,9 @@
#pragma once
#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
/*
* this is from GSM 03.03 CGI but is copied in GSM 08.08
@@ -416,3 +419,17 @@
GSM0808_PAGINF_FOR_SMS = 0x01,
GSM0808_PAGINF_FOR_USSD = 0x02,
};
+
+/* 3GPP TS 48.008 3.2.2.103 Speech Codec List */
+/* 3GPP TS 48.008 3.2.2.104 Speech Codec */
+struct gsm0808_speech_codec {
+ struct llist_head list;
+ bool fi;
+ bool pi;
+ bool pt;
+ bool tf;
+ uint8_t type;
+ uint16_t cfg;
+ bool type_extended;
+ bool cfg_present;
+};
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index d1897cf4..202f1ac 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -20,6 +20,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -30,6 +31,7 @@
#define IP_V4_ADDR_LEN 4
#define IP_V6_ADDR_LEN 16
#define IP_PORT_LEN 2
+
/* Encode AoIP transport address element */
struct msgb *gsm0808_enc_aoip_trasp_addr(struct sockaddr_storage *ss)
@@ -113,3 +115,175 @@
return ss;
}
+
+/* Helper function for gsm0808_enc_speech_codec()
+ * and gsm0808_enc_speech_codec_list() */
+static void enc_speech_codec(struct msgb *msg, struct gsm0808_speech_codec *sc)
+{
+ /* See also 3GPP TS 48.008 3.2.2.103 Speech Codec List */
+ uint8_t header = 0;
+
+ if (sc->fi)
+ header |= (1 << 7);
+ if (sc->pi)
+ header |= (1 << 6);
+ if (sc->pt)
+ header |= (1 << 5);
+ if (sc->tf)
+ header |= (1 << 4);
+ if (sc->type_extended) {
+ header |= 0x0f;
+ msgb_put_u8(msg, header);
+ } else {
+ OSMO_ASSERT(sc->type < 0x0f);
+ header |= sc->type;
+ msgb_put_u8(msg, header);
+ return;
+ }
+
+ msgb_put_u8(msg, sc->type);
+
+ if (sc->cfg_present)
+ msgb_put_u16(msg, sc->cfg);
+}
+
+/* Encode Speech Codec element */
+struct msgb *gsm0808_enc_speech_codec(struct gsm0808_speech_codec *sc)
+{
+ struct msgb *msg;
+
+ OSMO_ASSERT(sc);
+
+ msg = msgb_alloc(ELEMENT_MSGB_MAXLEN, "Speech Codec Element");
+ if (!msg)
+ return NULL;
+
+ enc_speech_codec(msg, sc);
+
+ return msg;
+}
+
+/* Decode Speech Codec element */
+struct gsm0808_speech_codec *gsm0808_dec_speech_codec(const void *ctx,
+ struct msgb *msg)
+{
+ /* See also 3GPP TS 48.008 3.2.2.103 Speech Codec List */
+ uint8_t header;
+ struct gsm0808_speech_codec *sc;
+
+ if (!msg)
+ return NULL;
+
+ /* Malformed elements */
+ if ((msg->data[0] & 0x0F) == 0x0F && msg->len < 2)
+ return NULL;
+ else if ((msg->data[0] & 0x0F) != 0x0F && msg->len < 1)
+ return NULL;
+
+ header = msgb_pull_u8(msg);
+ sc = talloc_zero(ctx, struct gsm0808_speech_codec);
+ if (!sc)
+ return NULL;
+
+ if (header & (1 << 7))
+ sc->fi = true;
+ if (header & (1 << 6))
+ sc->pi = true;
+ if (header & (1 << 5))
+ sc->pt = true;
+ if (header & (1 << 4))
+ sc->tf = true;
+
+ if ((header & 0x0F) != 0x0F) {
+ sc->type = (header & 0x0F);
+ return sc;
+ }
+
+ sc->type = msgb_pull_u8(msg);
+ sc->type_extended = true;
+
+ if (msg->len < 2)
+ return sc;
+
+ sc->cfg = msgb_pull_u16(msg);
+ sc->cfg_present = true;
+
+ return sc;
+}
+
+/* Encode Speech Codec list */
+struct msgb *gsm0808_enc_speech_codec_list(struct llist_head *scl)
+{
+ struct gsm0808_speech_codec *sc;
+ unsigned int scl_len;
+ struct msgb *msg;
+
+ OSMO_ASSERT(scl);
+
+ scl_len = llist_count(scl);
+
+ /* Empty list */
+ if (scl_len < 1)
+ return NULL;
+
+ msg =
+ msgb_alloc(ELEMENT_MSGB_MAXLEN * scl_len,
+ "Speech Codec Element");
+ if (!msg)
+ return NULL;
+
+ llist_for_each_entry(sc, scl, list) {
+ enc_speech_codec(msg, sc);
+ }
+
+ /* Prevent generating oversized TLV elements */
+ if (msg->len > ELEMENT_MSGB_MAXLEN) {
+ free(msg);
+ return NULL;
+ }
+
+ return msg;
+}
+
+/* Decode Speech Codec list */
+struct llist_head *gsm0808_dec_speech_codec_list(const void *ctx,
+ struct msgb *msg)
+{
+ struct llist_head *scl = NULL;
+ struct gsm0808_speech_codec *sc;
+ unsigned int loopcount = 0;
+ unsigned int scl_len;
+
+ if (!msg)
+ return NULL;
+
+ scl = talloc_zero(ctx, struct llist_head);
+ if (!scl)
+ return NULL;
+
+ INIT_LLIST_HEAD(scl);
+
+ while (1) {
+ /* Ensure loop exit */
+ if (loopcount > 255)
+ break;
+
+ sc = gsm0808_dec_speech_codec(scl, msg);
+ if (sc == NULL)
+ break;
+
+ llist_add(&sc->list, scl);
+
+ loopcount++;
+ }
+
+ scl_len = llist_count(scl);
+
+ /* Empty list */
+ if (scl_len < 1) {
+ talloc_free(scl);
+ return NULL;
+ }
+
+ return scl;
+}
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 3ad847d..c89cbe4 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -139,6 +139,10 @@
gsm0808_prepend_dtap_header;
gsm0808_enc_aoip_trasp_addr;
gsm0808_dec_aoip_trasp_addr;
+gsm0808_enc_speech_codec;
+gsm0808_dec_speech_codec;
+gsm0808_enc_speech_codec_list;
+gsm0808_dec_speech_codec_list;
gsm0858_rsl_ul_meas_enc;
diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c
index 99605d8..7f2cff1 100644
--- a/tests/gsm0808/gsm0808_test.c
+++ b/tests/gsm0808/gsm0808_test.c
@@ -307,6 +307,158 @@
msgb_free(msg);
}
+static void test_gsm0808_enc_dec_speech_codec(const void *ctx)
+{
+ struct gsm0808_speech_codec enc_sc;
+ struct gsm0808_speech_codec *dec_sc;
+ struct msgb *msg;
+
+ memset(&enc_sc, 0, sizeof(enc_sc));
+ enc_sc.fi = true;
+ enc_sc.pt = true;
+ enc_sc.type = 0x05;
+
+ msg = gsm0808_enc_speech_codec(&enc_sc);
+ OSMO_ASSERT(msg);
+ dec_sc = gsm0808_dec_speech_codec(ctx, msg);
+ OSMO_ASSERT(dec_sc);
+ OSMO_ASSERT(msg->len == 0);
+
+ OSMO_ASSERT(memcmp(&enc_sc, dec_sc, sizeof(enc_sc)) == 0);
+
+ talloc_free(dec_sc);
+ msgb_free(msg);
+}
+
+static void test_gsm0808_enc_dec_speech_codec_ext_with_cfg(const void *ctx)
+{
+ struct gsm0808_speech_codec enc_sc;
+ struct gsm0808_speech_codec *dec_sc;
+ struct msgb *msg;
+
+ enc_sc.pi = true;
+ enc_sc.tf = true;
+ enc_sc.type = 0xab;
+ enc_sc.type_extended = true;
+ enc_sc.cfg_present = true;
+ enc_sc.cfg = 0xcdef;
+
+ msg = gsm0808_enc_speech_codec(&enc_sc);
+ OSMO_ASSERT(msg);
+ dec_sc = gsm0808_dec_speech_codec(ctx, msg);
+ OSMO_ASSERT(dec_sc);
+ OSMO_ASSERT(msg->len == 0);
+
+ OSMO_ASSERT(memcmp(&enc_sc, dec_sc, sizeof(enc_sc)) == 0);
+
+ talloc_free(dec_sc);
+ msgb_free(msg);
+}
+
+static void test_gsm0808_enc_dec_speech_codec_ext(const void *ctx)
+{
+ struct gsm0808_speech_codec enc_sc;
+ struct gsm0808_speech_codec *dec_sc;
+ struct msgb *msg;
+
+ enc_sc.fi = true;
+ enc_sc.tf = true;
+ enc_sc.type = 0xf2;
+ enc_sc.type_extended = true;
+
+ msg = gsm0808_enc_speech_codec(&enc_sc);
+ OSMO_ASSERT(msg);
+ dec_sc = gsm0808_dec_speech_codec(ctx, msg);
+ OSMO_ASSERT(dec_sc);
+ OSMO_ASSERT(msg->len == 0);
+
+ OSMO_ASSERT(memcmp(&enc_sc, dec_sc, sizeof(enc_sc)) == 0);
+
+ talloc_free(dec_sc);
+ msgb_free(msg);
+}
+
+static bool speech_codec_cmp(struct gsm0808_speech_codec *a,
+ struct gsm0808_speech_codec *b)
+{
+ if (a->fi != b->fi)
+ return false;
+ if (a->pi != b->pi)
+ return false;
+ if (a->pt != b->pt)
+ return false;
+ if (a->tf != b->tf)
+ return false;
+ if (a->type != b->type)
+ return false;
+ if (a->cfg != b->cfg)
+ return false;
+ if (a->type_extended != b->type_extended)
+ return false;
+ if (a->cfg_present != b->cfg_present)
+ return false;
+
+ return true;
+}
+
+static void test_gsm0808_enc_dec_speech_codec_list(const void *ctx)
+{
+ struct gsm0808_speech_codec enc_sc1;
+ struct gsm0808_speech_codec enc_sc2;
+ struct gsm0808_speech_codec enc_sc3;
+ struct msgb *msg;
+ struct llist_head sc_list;
+ struct llist_head *sc_list_decoded;
+ struct gsm0808_speech_codec *sc;
+
+ INIT_LLIST_HEAD(&sc_list);
+
+ memset(&enc_sc1, 0, sizeof(enc_sc1));
+ enc_sc1.pi = true;
+ enc_sc1.tf = true;
+ enc_sc1.type = 0xab;
+ enc_sc1.type_extended = true;
+ enc_sc1.cfg_present = true;
+ enc_sc1.cfg = 0xcdef;
+
+ memset(&enc_sc2, 0, sizeof(enc_sc2));
+ enc_sc2.fi = true;
+ enc_sc2.pt = true;
+ enc_sc2.type = 0x05;
+
+ memset(&enc_sc3, 0, sizeof(enc_sc3));
+ enc_sc3.fi = true;
+ enc_sc3.tf = true;
+ enc_sc3.type = 0xf2;
+ enc_sc3.type_extended = true;
+
+ llist_add(&enc_sc3.list, &sc_list);
+ llist_add(&enc_sc2.list, &sc_list);
+ llist_add(&enc_sc1.list, &sc_list);
+
+ msg = gsm0808_enc_speech_codec_list(&sc_list);
+ sc_list_decoded = gsm0808_dec_speech_codec_list(ctx, msg);
+ OSMO_ASSERT(msg->len == 0);
+
+ llist_for_each_entry(sc, sc_list_decoded, list) {
+ if(sc->type == 0xab) {
+ OSMO_ASSERT(speech_codec_cmp(&enc_sc1,sc) == true);
+ }
+ else if(sc->type == 0x05) {
+ OSMO_ASSERT(speech_codec_cmp(&enc_sc2,sc) == true);
+ }
+ else if(sc->type == 0xf2) {
+ OSMO_ASSERT(speech_codec_cmp(&enc_sc3,sc) == true);
+ }
+ else {
+ OSMO_ASSERT(false);
+ }
+ }
+
+ talloc_free(sc_list_decoded);
+ msgb_free(msg);
+}
+
int main(int argc, char **argv)
{
void *ctx;
@@ -329,6 +481,10 @@
test_prepend_dtap();
test_enc_dec_aoip_trasp_addr_v4(ctx);
test_enc_dec_aoip_trasp_addr_v6(ctx);
+ test_gsm0808_enc_dec_speech_codec(ctx);
+ test_gsm0808_enc_dec_speech_codec_ext(ctx);
+ test_gsm0808_enc_dec_speech_codec_ext_with_cfg(ctx);
+ test_gsm0808_enc_dec_speech_codec_list(ctx);
printf("Done\n");
--
To view, visit https://gerrit.osmocom.org/2177
To unsubscribe, visit https://gerrit.osmocom.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0e1e2edf47adaa45b22d4b0bcae3640dba7ca200
Gerrit-PatchSet: 1
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Owner: dexter <pmaier at sysmocom.de>