summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/gsm/gsm_utils.h59
-rw-r--r--src/gsm/gsm0480.c11
-rw-r--r--src/gsm/gsm_utils.c145
-rw-r--r--src/gsm/libosmogsm.map7
-rw-r--r--tests/sms/sms_test.c124
-rw-r--r--tests/sms/sms_test.ok10
-rw-r--r--tests/ussd/ussd_test.c50
-rw-r--r--tests/ussd/ussd_test.ok11
8 files changed, 290 insertions, 127 deletions
diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h
index 6cd46e45..c111f94a 100644
--- a/include/osmocom/gsm/gsm_utils.h
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -25,6 +25,7 @@
#ifndef GSM_UTILS_H
#define GSM_UTILS_H
+#include <stddef.h>
#include <stdint.h>
#define ADD_MODULO(sum, delta, modulo) do { \
@@ -56,17 +57,54 @@ enum gsm_band {
const char *gsm_band_name(enum gsm_band band);
enum gsm_band gsm_band_parse(const char *mhz);
-int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length);
-int gsm_7bit_decode_ussd(char *decoded, const uint8_t *user_data, uint8_t length);
-int gsm_7bit_decode_hdr(char *decoded, const uint8_t *user_data, uint8_t length, uint8_t ud_hdr_ind);
-int gsm_7bit_encode(uint8_t *result, const char *data);
-int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets_written);
-int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets_written);
+/*!
+ * \brief Decode a sequence of GSM 03.38 encoded 7 bit characters.
+ *
+ * \param decoded The destination buffer for the decoded characters.
+ * \param n A maximum of n chars is written (incl. terminating \0).
+ * Requires n >= 1.
+ * \param user_data A pointer to the start of the packed 7bit character
+ * sequence.
+ * \param length The length of the input sequence (in octets).
+ *
+ * \returns the number of (8 bit) chars written excluding the terminating \0.
+ * This is the same like strlen(decoded).
+ */
+int gsm_7bit_decode_n(char *decoded, size_t n, const uint8_t *user_data, uint8_t length);
+
+/*!
+ * \brief Decode a sequence of 7 bit characters (USSD encoding).
+ *
+ * \see gsm_7bit_encode_n()
+ */
+int gsm_7bit_decode_n_ussd(char *decoded, size_t n, const uint8_t *user_data, uint8_t length);
+
+/**
+ * \brief Encode a text string into GSM 03.38 encoded 7 bit characters.
+ *
+ * \param result The destination buffer for the packed 7 bit sequence.
+ * \param n A maximum of n octets is written.
+ * \param data A pointer to the start of the \0 terminated 8 bit character
+ * string.
+ * \param octets_written Iff not NULL, *octets_written will be set to the
+ * number of octets written to the result buffer.
+ *
+ * \returns the number of septets that have been created.
+ */
+int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets_written);
-/* the three functions below are helper functions and here for the unit test */
+/*!
+ * \brief Encode a text string into GSM 03.38 encoded 7 bit characters (USSD encoding).
+ *
+ * \see gsm_7bit_decode_n()
+ */
+int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets_written);
+
+/* the four functions below are helper functions and here for the unit test */
int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding);
int gsm_septet_encode(uint8_t *result, const char *data);
uint8_t gsm_get_octet_len(const uint8_t sept_len);
+int gsm_7bit_decode_n_hdr(char *decoded, size_t n, const uint8_t *user_data, uint8_t length, uint8_t ud_hdr_ind);
unsigned int ms_class_gmsk_dbm(enum gsm_band band, int ms_class);
@@ -154,5 +192,12 @@ enum gsm_chan_t {
_GSM_LCHAN_MAX
};
+/* Deprectated functions */
+int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length) __attribute__((deprecated ("Use gsm_7bit_decode_n() instead")));
+int gsm_7bit_decode_ussd(char *decoded, const uint8_t *user_data, uint8_t length) __attribute__((deprecated ("Use gsm_7bit_decode_n_ussd() instead")));
+int gsm_7bit_encode(uint8_t *result, const char *data) __attribute__((deprecated ("Use gsm_7bit_encode_n() instead")));
+int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets_written) __attribute__((deprecated ("Use gsm_7bit_encode_n_ussd() instead")));
+int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets_written) __attribute__((deprecated ("Use gsm_7bit_encode_n() instead")));
+
#endif
diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c
index cc693feb..92a62dcf 100644
--- a/src/gsm/gsm0480.c
+++ b/src/gsm/gsm0480.c
@@ -105,7 +105,7 @@ struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *
msgb_put_u8(msg, ASN1_OCTET_STRING_TAG);
ussd_len_ptr = msgb_put(msg, 1);
data = msgb_put(msg, 0);
- gsm_7bit_encode_ussd(data, text, &len);
+ gsm_7bit_encode_n_ussd(data, msgb_tailroom(msg), text, &len);
msgb_put(msg, len);
ussd_len_ptr[0] = len;
/* USSD-String } */
@@ -172,7 +172,7 @@ struct msgb *gsm0480_create_notifySS(const char *text)
msgb_put_u8(msg, 0x82);
tmp_len = msgb_put(msg, 1);
data = msgb_put(msg, 0);
- gsm_7bit_encode_ussd(data, text, &len);
+ gsm_7bit_encode_n_ussd(data, msgb_tailroom(msg), text, &len);
tmp_len[0] = len;
msgb_put(msg, len);
@@ -398,10 +398,7 @@ static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length,
if ((dcs == 0x0F) &&
(uss_req_data[5] == ASN1_OCTET_STRING_TAG)) {
num_chars = (uss_req_data[6] * 8) / 7;
- /* Prevent a mobile-originated buffer-overrun! */
- if (num_chars > MAX_LEN_USSD_STRING)
- num_chars = MAX_LEN_USSD_STRING;
- gsm_7bit_decode_ussd(req->text,
+ gsm_7bit_decode_n_ussd(req->text, sizeof(req->text),
&(uss_req_data[7]), num_chars);
rc = 1;
}
@@ -423,7 +420,7 @@ struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const
/* First put the payload text into the message */
ptr8 = msgb_put(msg, 0);
- gsm_7bit_encode_ussd(ptr8, text, &response_len);
+ gsm_7bit_encode_n_ussd(ptr8, msgb_tailroom(msg), text, &response_len);
msgb_put(msg, response_len);
/* Then wrap it as an Octet String */
diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c
index 3dd15375..e248078f 100644
--- a/src/gsm/gsm_utils.c
+++ b/src/gsm/gsm_utils.c
@@ -28,7 +28,7 @@
* This library is a collection of common code used in various
* GSM related sub-projects inside the Osmocom family of projects. It
* includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation,
- * a GSM TLV parser, SMS utility routines as well as
+ * a GSM TLV parser, SMS utility routines as well as
* protocol definitions for a series of protocols:
* * Um L2 (04.06)
* * Um L3 (04.08)
@@ -123,12 +123,17 @@ uint8_t gsm_get_octet_len(const uint8_t sept_len){
}
/* GSM 03.38 6.2.1 Character unpacking */
-int gsm_7bit_decode_hdr(char *text, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
+int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
{
int i = 0;
int shift = 0;
- uint8_t c;
+ uint8_t c7, c8;
uint8_t next_is_ext = 0;
+ const char *text_buf_begin = text;
+ const char *text_buf_end = text + n;
+ int nchars;
+
+ OSMO_ASSERT (n > 0);
/* skip the user data header */
if (ud_hdr_ind) {
@@ -139,50 +144,49 @@ int gsm_7bit_decode_hdr(char *text, const uint8_t *user_data, uint8_t septet_l,
septet_l = septet_l - shift;
}
- for (i = 0; i < septet_l; i++) {
- c =
+ for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
+ c7 =
((user_data[((i + shift) * 7 + 7) >> 3] <<
(7 - (((i + shift) * 7 + 7) & 7))) |
(user_data[((i + shift) * 7) >> 3] >>
(((i + shift) * 7) & 7))) & 0x7f;
- /* this is an extension character */
if (next_is_ext) {
+ /* this is an extension character */
next_is_ext = 0;
- *(text++) = gsm_7bit_alphabet[0x7f + c];
- continue;
- }
-
- if (c == 0x1b && i + 1 < septet_l) {
+ c8 = gsm_7bit_alphabet[0x7f + c7];
+ } else if (c7 == 0x1b && i + 1 < septet_l) {
next_is_ext = 1;
+ continue;
} else {
- *(text++) = gsm_septet_lookup(c);
+ c8 = gsm_septet_lookup(c7);
}
+
+ *(text++) = c8;
}
- if (ud_hdr_ind)
- i += shift;
+ nchars = text - text_buf_begin;
+
*text = '\0';
- return i;
+ return nchars;
}
-int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
+int gsm_7bit_decode_n(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l)
{
- return gsm_7bit_decode_hdr(text, user_data, septet_l, 0);
+ return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
}
-int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
+int gsm_7bit_decode_n_ussd(char *text, size_t n, const uint8_t *user_data, uint8_t length)
{
- int i;
+ int nchars;
- gsm_7bit_decode_hdr(text, user_data, length, 0);
- i = strlen(text);
+ nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
/* remove last <CR>, if it fits up to the end of last octet */
- if (i && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
- text[--i] = '\0';
+ if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
+ text[--nchars] = '\0';
- return i;
+ return nchars;
}
/* GSM 03.38 6.2.1 Prepare character packing */
@@ -261,38 +265,28 @@ int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len
}
/* GSM 03.38 6.2.1 Character packing */
-int gsm_7bit_encode(uint8_t *result, const char *data)
-{
- int out;
- return gsm_7bit_encode_oct(result, data, &out);
-}
-
-int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
-{
- int y;
-
- y = gsm_7bit_encode_oct(result, data, octets);
- /* if last octet contains only one bit, add <CR> */
- if (((y * 7) & 7) == 1)
- result[(*octets) - 1] |= ('\r' << 1);
- /* if last character is <CR> and completely fills last octet, add
- * another <CR>. */
- if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r') {
- result[(*octets)++] = '\r';
- y++;
- }
-
- return y;
-}
-
-int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
+int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
{
int y = 0;
+ int o;
+ int max_septets = n * 8 / 7;
/* prepare for the worst case, every character expanding to two bytes */
uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
y = gsm_septet_encode(rdata, data);
- *octets = gsm_septets2octets(result, rdata, y, 0);
+
+ if (y > max_septets) {
+ /*
+ * Limit the number of septets to avoid the generation
+ * of more than n octets.
+ */
+ y = max_septets;
+ }
+
+ o = gsm_septets2octets(result, rdata, y, 0);
+
+ if (octets)
+ *octets = o;
free(rdata);
@@ -309,6 +303,24 @@ int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
return y;
}
+int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
+{
+ int y;
+
+ y = gsm_7bit_encode_n(result, n, data, octets);
+ /* if last octet contains only one bit, add <CR> */
+ if (((y * 7) & 7) == 1)
+ result[(*octets) - 1] |= ('\r' << 1);
+ /* if last character is <CR> and completely fills last octet, add
+ * another <CR>. */
+ if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
+ result[(*octets)++] = '\r';
+ y++;
+ }
+
+ return y;
+}
+
/* convert power class to dBm according to GSM TS 05.05 */
unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
{
@@ -373,7 +385,7 @@ int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
case GSM_BAND_1800:
if (dbm >= 36)
return 29;
- else if (dbm >= 34)
+ else if (dbm >= 34)
return 30;
else if (dbm >= 32)
return 31;
@@ -662,3 +674,34 @@ uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
}
return tlli;
}
+
+/* Wrappers for deprecated functions: */
+
+int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
+{
+ gsm_7bit_decode_n(text, SIZE_MAX, user_data, septet_l);
+
+ /* Mimic the original behaviour. */
+ return septet_l;
+}
+
+int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
+{
+ return gsm_7bit_decode_n_ussd(text, SIZE_MAX, user_data, length);
+}
+
+int gsm_7bit_encode(uint8_t *result, const char *data)
+{
+ int out;
+ return gsm_7bit_encode_n(result, SIZE_MAX, data, &out);
+}
+
+int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
+{
+ return gsm_7bit_encode_n_ussd(result, SIZE_MAX, data, octets);
+}
+
+int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
+{
+ return gsm_7bit_encode_n(result, SIZE_MAX, data, octets);
+}
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 1b985e10..9d15d668 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -133,11 +133,16 @@ gsm48_rr_att_tlvdef;
gsm_7bit_decode;
gsm_7bit_decode_ussd;
-gsm_7bit_decode_hdr;
gsm_7bit_encode;
gsm_7bit_encode_ussd;
gsm_7bit_encode_oct;
+gsm_7bit_decode_n;
+gsm_7bit_decode_n_ussd;
+gsm_7bit_decode_n_hdr;
+gsm_7bit_encode_n;
+gsm_7bit_encode_n_ussd;
+
gsm_arfcn2band;
gsm_arfcn2freq10;
gsm_freq102arfcn;
diff --git a/tests/sms/sms_test.c b/tests/sms/sms_test.c
index e48f9a36..3188a187 100644
--- a/tests/sms/sms_test.c
+++ b/tests/sms/sms_test.c
@@ -116,14 +116,14 @@ static const uint8_t concatenated_part2_enc[] = {
static const struct test_case test_multiple_encode[] =
{
{
- .input = concatenated_text,
+ .input = (const uint8_t *) concatenated_text,
.expected = concatenated_part1_enc,
.expected_octet_length = sizeof(concatenated_part1_enc),
.expected_septet_length = concatenated_part1_septet_length,
.ud_hdr_ind = 1,
},
{
- .input = concatenated_text,
+ .input = (const uint8_t *) concatenated_text,
.expected = concatenated_part2_enc,
.expected_octet_length = sizeof(concatenated_part2_enc),
.expected_septet_length = concatenated_part2_septet_length,
@@ -134,28 +134,28 @@ static const struct test_case test_multiple_encode[] =
static const struct test_case test_encode[] =
{
{
- .input = simple_text,
+ .input = (const uint8_t *) simple_text,
.expected = simple_enc,
.expected_octet_length = sizeof(simple_enc),
.expected_septet_length = simple_septet_length,
.ud_hdr_ind = 0,
},
{
- .input = escape_text,
+ .input = (const uint8_t *) escape_text,
.expected = escape_enc,
.expected_octet_length = sizeof(escape_enc),
.expected_septet_length = escape_septet_length,
.ud_hdr_ind = 0,
},
{
- .input = enhanced_text,
+ .input = (const uint8_t *) enhanced_text,
.expected = enhanced_enc,
.expected_octet_length = sizeof(enhanced_enc),
.expected_septet_length = enhanced_septet_length,
.ud_hdr_ind = 0,
},
{
- .input = enhancedV2_text,
+ .input = (const uint8_t *) enhancedV2_text,
.expected = enhancedV2_enc,
.expected_octet_length = sizeof(enhancedV2_enc),
.expected_septet_length = enhancedV2_septet_length,
@@ -168,42 +168,42 @@ static const struct test_case test_decode[] =
{
.input = simple_enc,
.input_length = sizeof(simple_enc),
- .expected = simple_text,
+ .expected = (const uint8_t *) simple_text,
.expected_septet_length = simple_septet_length,
.ud_hdr_ind = 0,
},
{
.input = escape_enc,
.input_length = sizeof(escape_enc),
- .expected = escape_text,
+ .expected = (const uint8_t *) escape_text,
.expected_septet_length = escape_septet_length,
.ud_hdr_ind = 0,
},
{
.input = enhanced_enc,
.input_length = sizeof(enhanced_enc),
- .expected = enhanced_text,
+ .expected = (const uint8_t *) enhanced_text,
.expected_septet_length = enhanced_septet_length,
.ud_hdr_ind = 0,
},
{
.input = enhancedV2_enc,
.input_length = sizeof(enhancedV2_enc),
- .expected = enhancedV2_text,
+ .expected = (const uint8_t *) enhancedV2_text,
.expected_septet_length = enhancedV2_septet_length,
.ud_hdr_ind = 0,
},
{
.input = concatenated_part1_enc,
.input_length = sizeof(concatenated_part1_enc),
- .expected = splitted_text_part1,
+ .expected = (const uint8_t *) splitted_text_part1,
.expected_septet_length = concatenated_part1_septet_length_with_header,
.ud_hdr_ind = 1,
},
{
.input = concatenated_part2_enc,
.input_length = sizeof(concatenated_part2_enc),
- .expected = splitted_text_part2,
+ .expected = (const uint8_t *) splitted_text_part2,
.expected_septet_length = concatenated_part2_septet_length_with_header,
.ud_hdr_ind = 1,
},
@@ -216,7 +216,7 @@ static void test_octet_return()
printf("Encoding some tests and printing number of septets/octets\n");
- septets = gsm_7bit_encode_oct((uint8_t *) out, "test1234", &oct);
+ septets = gsm_7bit_encode_n((uint8_t *) out, sizeof(out), "test1234", &oct);
printf("SEPTETS: %d OCTETS: %d\n", septets, oct);
printf("Done\n");
@@ -227,43 +227,58 @@ int main(int argc, char** argv)
printf("SMS testing\n");
struct msgb *msg;
uint8_t i;
-
+ uint16_t buffer_size;
uint8_t octet_length;
+ int octets_written;
+ uint8_t computed_octet_length;
uint8_t septet_length;
uint8_t gsm_septet_length;
uint8_t coded[256];
uint8_t tmp[160];
uint8_t septet_data[256];
uint8_t ud_header[6];
+ int nchars;
char result[256];
/* test 7-bit encoding */
for (i = 0; i < ARRAY_SIZE(test_encode); ++i) {
memset(coded, 0x42, sizeof(coded));
- septet_length = gsm_7bit_encode(coded, test_encode[i].input);
- octet_length = gsm_get_octet_len(septet_length);
- if (octet_length != test_encode[i].expected_octet_length) {
- fprintf(stderr, "Encode case %d: Octet length failure. Got %d, expected %d\n",
- i, octet_length, test_encode[i].expected_octet_length);
- return -1;
- }
-
- if (septet_length != test_encode[i].expected_septet_length){
- fprintf(stderr, "Encode case %d: Septet length failure. Got %d, expected %d\n",
- i, septet_length, test_encode[i].expected_septet_length);
- return -1;
- }
-
- if (memcmp(coded, test_encode[i].expected, octet_length) != 0) {
- fprintf(stderr, "Encoded content does not match for case %d\n",
- i);
- return -1;
+ septet_length = gsm_7bit_encode_n(coded, sizeof(coded),
+ (const char *) test_encode[i].input,
+ &octets_written);
+ computed_octet_length = gsm_get_octet_len(septet_length);
+ printf("Encode case %d: "
+ "Octet length %d (expected %d, computed %d), "
+ "septet length %d (expected %d)\n"
+ , i
+ , octets_written, test_encode[i].expected_octet_length, computed_octet_length
+ , septet_length, test_encode[i].expected_septet_length
+ );
+
+ OSMO_ASSERT (octets_written == test_encode[i].expected_octet_length);
+ OSMO_ASSERT (octets_written == computed_octet_length);
+ OSMO_ASSERT (memcmp(coded, test_encode[i].expected, octets_written) == 0);
+
+ /* check buffer limiting */
+ memset(coded, 0xaa, sizeof(coded));
+
+ for (buffer_size = 0;
+ buffer_size < test_encode[i].expected_octet_length + 1
+ && buffer_size < sizeof(coded) - 1;
+ ++buffer_size)
+ {
+ gsm_7bit_encode_n(coded, buffer_size,
+ (const char *) test_encode[i].input,
+ &octets_written);
+
+ OSMO_ASSERT(octets_written <= buffer_size);
+ OSMO_ASSERT(coded[buffer_size] == 0xaa);
}
}
/* Test: encode multiple SMS */
- int number_of_septets = gsm_septet_encode(septet_data, test_multiple_encode[0].input);
+ int number_of_septets = gsm_septet_encode(septet_data, (const char *) test_multiple_encode[0].input);
/* SMS part 1 */
memset(tmp, 0x42, sizeof(tmp));
@@ -281,11 +296,7 @@ int main(int argc, char** argv)
memset(coded, 0x42, sizeof(coded));
memcpy(coded, tmp, octet_length + 6);
- if (memcmp(coded, test_multiple_encode[0].expected, octet_length) != 0) {
- fprintf(stderr, "Multiple-SMS encoded content does not match for part 1\n");
- return -1;
- }
-
+ OSMO_ASSERT(memcmp(coded, test_multiple_encode[0].expected, octet_length) == 0);
/* SMS part 2 */
memset(tmp, 0x42, sizeof(tmp));
@@ -303,27 +314,32 @@ int main(int argc, char** argv)
memset(coded, 0x42, sizeof(coded));
memcpy(coded, tmp, octet_length + 6);
- if (memcmp(coded, test_multiple_encode[1].expected, octet_length) != 0) {
- fprintf(stderr, "Multiple-SMS encoded content does not match for part 2\n");
- return -1;
- }
-
-
+ OSMO_ASSERT(memcmp(coded, test_multiple_encode[1].expected, octet_length) == 0);
/* test 7-bit decoding */
for (i = 0; i < ARRAY_SIZE(test_decode); ++i) {
- memset(result, 0x42, sizeof(coded));
- septet_length = gsm_7bit_decode_hdr(result, test_decode[i].input,
+ memset(result, 0x42, sizeof(result));
+ nchars = gsm_7bit_decode_n_hdr(result, sizeof(result), test_decode[i].input,
test_decode[i].expected_septet_length, test_decode[i].ud_hdr_ind);
+ printf("Decode case %d: return value %d (expected %d)\n", i, nchars, strlen(result));
- if (strcmp(result, test_decode[i].expected) != 0) {
- fprintf(stderr, "Test case %d failed to decode.\n", i);
- return -1;
- }
- if (septet_length != test_decode[i].expected_septet_length) {
- fprintf(stderr, "Decode case %d: Septet length failure. Got %d, expected %d\n",
- i, septet_length, test_decode[i].expected_septet_length);
- return -1;
+ OSMO_ASSERT(strcmp(result, (const char *) test_decode[i].expected) == 0);
+ OSMO_ASSERT(nchars == strlen(result));
+
+ /* check buffer limiting */
+ memset(result, 0xaa, sizeof(result));
+
+ for (buffer_size = 1;
+ buffer_size < test_encode[i].expected_septet_length + 1
+ && buffer_size < sizeof(result) - 1;
+ ++buffer_size)
+ {
+ nchars = gsm_7bit_decode_n_hdr(result, buffer_size, test_decode[i].input,
+ test_decode[i].expected_septet_length, test_decode[i].ud_hdr_ind);
+
+ OSMO_ASSERT(nchars <= buffer_size);
+ OSMO_ASSERT(result[buffer_size] == (char)0xaa);
+ OSMO_ASSERT(result[nchars] == '\0');
}
}
diff --git a/tests/sms/sms_test.ok b/tests/sms/sms_test.ok
index ce6cb178..915a59c8 100644
--- a/tests/sms/sms_test.ok
+++ b/tests/sms/sms_test.ok
@@ -1,4 +1,14 @@
SMS testing
+Encode case 0: Octet length 8 (expected 8, computed 8), septet length 9 (expected 9)
+Encode case 1: Octet length 36 (expected 36, computed 36), septet length 41 (expected 41)
+Encode case 2: Octet length 35 (expected 35, computed 35), septet length 39 (expected 39)
+Encode case 3: Octet length 35 (expected 35, computed 35), septet length 40 (expected 40)
+Decode case 0: return value 9 (expected 9)
+Decode case 1: return value 40 (expected 40)
+Decode case 2: return value 31 (expected 31)
+Decode case 3: return value 32 (expected 32)
+Decode case 4: return value 153 (expected 153)
+Decode case 5: return value 40 (expected 40)
Encoding some tests and printing number of septets/octets
SEPTETS: 8 OCTETS: 7
Done
diff --git a/tests/ussd/ussd_test.c b/tests/ussd/ussd_test.c
index e3e8e08a..b04f8e8a 100644
--- a/tests/ussd/ussd_test.c
+++ b/tests/ussd/ussd_test.c
@@ -73,20 +73,42 @@ static void test_7bit_ussd(const char *text, const char *encoded_hex, const char
{
uint8_t coded[256];
char decoded[256];
- int y;
+ int octets_written;
+ int buffer_size;
+ int nchars;
printf("original = %s\n", osmo_hexdump((uint8_t *)text, strlen(text)));
- gsm_7bit_encode_ussd(coded, text, &y);
- printf("encoded = %s\n", osmo_hexdump(coded, y));
+ gsm_7bit_encode_n_ussd(coded, sizeof(coded), text, &octets_written);
+ printf("encoded = %s\n", osmo_hexdump(coded, octets_written));
- OSMO_ASSERT(strcmp(encoded_hex, osmo_hexdump_nospc(coded, y)) == 0);
+ OSMO_ASSERT(strcmp(encoded_hex, osmo_hexdump_nospc(coded, octets_written)) == 0);
- gsm_7bit_decode_ussd(decoded, coded, y * 8 / 7);
- y = strlen(decoded);
- printf("decoded = %s\n\n", osmo_hexdump((uint8_t *)decoded, y));
+ gsm_7bit_decode_n_ussd(decoded, sizeof(decoded), coded, octets_written * 8 / 7);
+ octets_written = strlen(decoded);
+ printf("decoded = %s\n\n", osmo_hexdump((uint8_t *)decoded, octets_written));
OSMO_ASSERT(strncmp(text, decoded, strlen(text)) == 0);
OSMO_ASSERT(strcmp(appended_after_decode, decoded + strlen(text)) == 0);
+
+ /* check buffer limiting */
+ memset(decoded, 0xaa, sizeof(decoded));
+
+ for (buffer_size = 1; buffer_size < sizeof(decoded) - 1; ++buffer_size)
+ {
+ nchars = gsm_7bit_decode_n_ussd(decoded, buffer_size, coded, octets_written * 8 / 7);
+ OSMO_ASSERT(nchars <= buffer_size);
+ OSMO_ASSERT(decoded[buffer_size] == (char)0xaa);
+ OSMO_ASSERT(decoded[nchars] == '\0');
+ }
+
+ memset(coded, 0xaa, sizeof(coded));
+
+ for (buffer_size = 0; buffer_size < sizeof(coded) - 1; ++buffer_size)
+ {
+ gsm_7bit_encode_n_ussd(coded, buffer_size, text, &octets_written);
+ OSMO_ASSERT(octets_written <= buffer_size);
+ OSMO_ASSERT(coded[buffer_size] == 0xaa);
+ }
}
int main(int argc, char **argv)
@@ -94,6 +116,7 @@ int main(int argc, char **argv)
struct ussd_request req;
const int size = sizeof(ussd_request);
int i;
+ struct msgb *msg;
osmo_init_logging(&info);
@@ -122,5 +145,18 @@ int main(int argc, char **argv)
test_7bit_ussd("0123456\r", "b0986c46abd91a0d", "\r");
test_7bit_ussd("012345\r", "b0986c46ab351a", "");
+ printf("Checking GSM 04.80 USSD message generation.\n");
+
+ test_7bit_ussd("", "", "");
+ msg = gsm0480_create_unstructuredSS_Notify (0x00, "");
+ printf ("Created unstructuredSS_Notify (0x00): %s\n",
+ osmo_hexdump(msgb_data(msg), msgb_length(msg)));
+ msgb_free (msg);
+
+ test_7bit_ussd("forty-two", "e6b79c9e6fd1ef6f", "");
+ msg = gsm0480_create_unstructuredSS_Notify (0x42, "forty-two");
+ printf ("Created unstructuredSS_Notify (0x42): %s\n",
+ osmo_hexdump(msgb_data(msg), msgb_length(msg)));
+ msgb_free (msg);
return 0;
}
diff --git a/tests/ussd/ussd_test.ok b/tests/ussd/ussd_test.ok
index 91f2a315..54d59eef 100644
--- a/tests/ussd/ussd_test.ok
+++ b/tests/ussd/ussd_test.ok
@@ -72,3 +72,14 @@ original = 30 31 32 33 34 35 0d
encoded = b0 98 6c 46 ab 35 1a
decoded = 30 31 32 33 34 35 0d
+Checking GSM 04.80 USSD message generation.
+original =
+encoded =
+decoded =
+
+Created unstructuredSS_Notify (0x00): 30 08 04 01 0f 04 00 04 01 00
+original = 66 6f 72 74 79 2d 74 77 6f
+encoded = e6 b7 9c 9e 6f d1 ef 6f
+decoded = 66 6f 72 74 79 2d 74 77 6f
+
+Created unstructuredSS_Notify (0x42): 30 10 04 01 0f 04 08 e6 b7 9c 9e 6f d1 ef 6f 04 01 42