blob: 3188a187a5f98348167c0af5f2edc773a3d127c2 [file] [log] [blame]
Harald Welteec8b4502010-02-20 20:34:29 +01001/*
2 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
Nico Golde28de0532010-07-09 17:19:12 +02003 * (C) 2010 by Nico Golde <nico@ngolde.de>
Harald Welteec8b4502010-02-20 20:34:29 +01004 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010025#include <osmocom/core/msgb.h>
26#include <osmocom/gsm/gsm_utils.h>
27#include <osmocom/core/utils.h>
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080028
29struct test_case {
30 const uint8_t *input;
31 const uint16_t input_length;
32
33 const uint8_t *expected;
Dennis Wehrle291e6132011-07-24 20:14:13 +020034 const uint16_t expected_octet_length;
35 const uint16_t expected_septet_length;
36 const uint8_t ud_hdr_ind;
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080037};
38
39static const char simple_text[] = "test text";
Dennis Wehrle291e6132011-07-24 20:14:13 +020040#define simple_septet_length 9
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080041static const uint8_t simple_enc[] = {
Nico Goldec0ce9aa2010-07-20 15:43:58 +020042 0xf4, 0xf2, 0x9c, 0x0e, 0xa2, 0x97, 0xf1, 0x74
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080043};
44
Dennis Wehrle291e6132011-07-24 20:14:13 +020045static const char escape_text[] = "!$ a more#^- complicated test@@?_%! case";
46#define escape_septet_length 41 /* note: the ^ counts as two, because it is a extension character */
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080047static const uint8_t escape_enc[] = {
48 0x21, 0x01, 0x28, 0x0c, 0x6a, 0xbf, 0xe5, 0xe5, 0xd1,
49 0x86, 0xd2, 0x02, 0x8d, 0xdf, 0x6d, 0x38, 0x3b, 0x3d,
50 0x0e, 0xd3, 0xcb, 0x64, 0x10, 0xbd, 0x3c, 0xa7, 0x03,
51 0x00, 0xbf, 0x48, 0x29, 0x04, 0x1a, 0x87, 0xe7, 0x65,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080052};
53
Dennis Wehrle291e6132011-07-24 20:14:13 +020054static const char enhanced_text[] = "enhanced ^ {][} test |+~ ^ test";
55#define enhanced_septet_length 39 /* note: the characters { } [ ] ^ | ~ count as two (each of them), because they are extension characters */
56static const uint8_t enhanced_enc[] = {
57 0x65, 0x37, 0x3A, 0xEC, 0x1E, 0x97, 0xC9, 0xA0, 0x0D,
58 0x05, 0xB4, 0x41, 0x6D, 0x7C, 0x1B, 0xDE, 0x26, 0x05,
59 0xA2, 0x97, 0xE7, 0x74, 0xD0, 0x06, 0xB8, 0xDA, 0xF4,
60 0x40, 0x1B, 0x0A, 0x88, 0x5E, 0x9E, 0xD3, 0x01,
61};
62
63static const char enhancedV2_text[] = "enhanced ^ {][} test |+~ ^ tests";
64#define enhancedV2_septet_length 40 /* note: number of octets are equal to the enhanced_text! */
65static const uint8_t enhancedV2_enc[] = {
66 0x65, 0x37, 0x3A, 0xEC, 0x1E, 0x97, 0xC9, 0xA0, 0x0D,
67 0x05, 0xB4, 0x41, 0x6D, 0x7C, 0x1B, 0xDE, 0x26, 0x05,
68 0xA2, 0x97, 0xE7, 0x74, 0xD0, 0x06, 0xB8, 0xDA, 0xF4,
69 0x40, 0x1B, 0x0A, 0x88, 0x5E, 0x9E, 0xD3, 0xE7,
70};
71
72
73
74static const char concatenated_text[] =
75 "this is a testmessage. this is a testmessage. this is a testmessage. this is a testmessage. "
76 "this is a testmessage. this is a testmessage. cut here .....: this is a second testmessage. end here.";
77
78static const char splitted_text_part1[] =
79 "this is a testmessage. this is a testmessage. this is a testmessage. this is a testmessage. "
80 "this is a testmessage. this is a testmessage. cut here .....:";
81#define concatenated_part1_septet_length_with_header 160
82#define concatenated_part1_septet_length 153
83static const uint8_t concatenated_part1_enc[] = {
84 0x05, 0x00, 0x03, 0x6f, 0x02, 0x01,
85 0xe8, 0xe8, 0xf4, 0x1c, 0x94, 0x9e, 0x83, 0xc2,
86 0x20, 0x7a, 0x79, 0x4e, 0x6f, 0x97, 0xe7, 0xf3,
87 0xf0, 0xb9, 0xec, 0x02, 0xd1, 0xd1, 0xe9, 0x39,
88 0x28, 0x3d, 0x07, 0x85, 0x41, 0xf4, 0xf2, 0x9c,
89 0xde, 0x2e, 0xcf, 0xe7, 0xe1, 0x73, 0xd9, 0x05,
90 0xa2, 0xa3, 0xd3, 0x73, 0x50, 0x7a, 0x0e, 0x0a,
91 0x83, 0xe8, 0xe5, 0x39, 0xbd, 0x5d, 0x9e, 0xcf,
92 0xc3, 0xe7, 0xb2, 0x0b, 0x44, 0x47, 0xa7, 0xe7,
93 0xa0, 0xf4, 0x1c, 0x14, 0x06, 0xd1, 0xcb, 0x73,
94 0x7a, 0xbb, 0x3c, 0x9f, 0x87, 0xcf, 0x65, 0x17,
95 0x88, 0x8e, 0x4e, 0xcf, 0x41, 0xe9, 0x39, 0x28,
96 0x0c, 0xa2, 0x97, 0xe7, 0xf4, 0x76, 0x79, 0x3e,
97 0x0f, 0x9f, 0xcb, 0x2e, 0x10, 0x1d, 0x9d, 0x9e,
98 0x83, 0xd2, 0x73, 0x50, 0x18, 0x44, 0x2f, 0xcf,
99 0xe9, 0xed, 0xf2, 0x7c, 0x1e, 0x3e, 0x97, 0x5d,
100 0xa0, 0x71, 0x9d, 0x0e, 0x42, 0x97, 0xe5, 0x65,
101 0x90, 0xcb, 0xe5, 0x72, 0xb9, 0x74,
102};
103
104static const char splitted_text_part2[] = " this is a second testmessage. end here.";
105#define concatenated_part2_septet_length_with_header 47
106#define concatenated_part2_septet_length 40
107static const uint8_t concatenated_part2_enc[] = {
108 0x05, 0x00, 0x03, 0x6f, 0x02, 0x02,
109 0x40, 0x74, 0x74, 0x7a, 0x0e, 0x4a, 0xcf, 0x41,
110 0x61, 0xd0, 0xbc, 0x3c, 0x7e, 0xbb, 0xc9, 0x20,
111 0x7a, 0x79, 0x4e, 0x6f, 0x97, 0xe7, 0xf3, 0xf0,
112 0xb9, 0xec, 0x02, 0x95, 0xdd, 0x64, 0x10, 0xba,
113 0x2c, 0x2f, 0xbb, 0x00,
114};
115
116static const struct test_case test_multiple_encode[] =
117{
118 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200119 .input = (const uint8_t *) concatenated_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200120 .expected = concatenated_part1_enc,
121 .expected_octet_length = sizeof(concatenated_part1_enc),
122 .expected_septet_length = concatenated_part1_septet_length,
123 .ud_hdr_ind = 1,
124 },
125 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200126 .input = (const uint8_t *) concatenated_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200127 .expected = concatenated_part2_enc,
128 .expected_octet_length = sizeof(concatenated_part2_enc),
129 .expected_septet_length = concatenated_part2_septet_length,
130 .ud_hdr_ind = 1,
131 },
132};
133
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800134static const struct test_case test_encode[] =
135{
136 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200137 .input = (const uint8_t *) simple_text,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800138 .expected = simple_enc,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200139 .expected_octet_length = sizeof(simple_enc),
140 .expected_septet_length = simple_septet_length,
141 .ud_hdr_ind = 0,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800142 },
143 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200144 .input = (const uint8_t *) escape_text,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800145 .expected = escape_enc,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200146 .expected_octet_length = sizeof(escape_enc),
147 .expected_septet_length = escape_septet_length,
148 .ud_hdr_ind = 0,
149 },
150 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200151 .input = (const uint8_t *) enhanced_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200152 .expected = enhanced_enc,
153 .expected_octet_length = sizeof(enhanced_enc),
154 .expected_septet_length = enhanced_septet_length,
155 .ud_hdr_ind = 0,
156 },
157 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200158 .input = (const uint8_t *) enhancedV2_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200159 .expected = enhancedV2_enc,
160 .expected_octet_length = sizeof(enhancedV2_enc),
161 .expected_septet_length = enhancedV2_septet_length,
162 .ud_hdr_ind = 0,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800163 },
164};
165
166static const struct test_case test_decode[] =
167{
168 {
169 .input = simple_enc,
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200170 .input_length = sizeof(simple_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200171 .expected = (const uint8_t *) simple_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200172 .expected_septet_length = simple_septet_length,
173 .ud_hdr_ind = 0,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800174 },
175 {
176 .input = escape_enc,
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200177 .input_length = sizeof(escape_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200178 .expected = (const uint8_t *) escape_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200179 .expected_septet_length = escape_septet_length,
180 .ud_hdr_ind = 0,
181 },
182 {
183 .input = enhanced_enc,
184 .input_length = sizeof(enhanced_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200185 .expected = (const uint8_t *) enhanced_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200186 .expected_septet_length = enhanced_septet_length,
187 .ud_hdr_ind = 0,
188 },
189 {
190 .input = enhancedV2_enc,
191 .input_length = sizeof(enhancedV2_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200192 .expected = (const uint8_t *) enhancedV2_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200193 .expected_septet_length = enhancedV2_septet_length,
194 .ud_hdr_ind = 0,
195 },
196 {
197 .input = concatenated_part1_enc,
198 .input_length = sizeof(concatenated_part1_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200199 .expected = (const uint8_t *) splitted_text_part1,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200200 .expected_septet_length = concatenated_part1_septet_length_with_header,
201 .ud_hdr_ind = 1,
202 },
203 {
204 .input = concatenated_part2_enc,
205 .input_length = sizeof(concatenated_part2_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200206 .expected = (const uint8_t *) splitted_text_part2,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200207 .expected_septet_length = concatenated_part2_septet_length_with_header,
208 .ud_hdr_ind = 1,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800209 },
210};
Harald Welteec8b4502010-02-20 20:34:29 +0100211
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200212static void test_octet_return()
213{
214 char out[256];
215 int oct, septets;
216
217 printf("Encoding some tests and printing number of septets/octets\n");
218
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200219 septets = gsm_7bit_encode_n((uint8_t *) out, sizeof(out), "test1234", &oct);
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200220 printf("SEPTETS: %d OCTETS: %d\n", septets, oct);
221
222 printf("Done\n");
223}
224
Harald Welteec8b4502010-02-20 20:34:29 +0100225int main(int argc, char** argv)
226{
227 printf("SMS testing\n");
228 struct msgb *msg;
Harald Welteec8b4502010-02-20 20:34:29 +0100229 uint8_t i;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200230 uint16_t buffer_size;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200231 uint8_t octet_length;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200232 int octets_written;
233 uint8_t computed_octet_length;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200234 uint8_t septet_length;
235 uint8_t gsm_septet_length;
Harald Welteec8b4502010-02-20 20:34:29 +0100236 uint8_t coded[256];
Dennis Wehrle291e6132011-07-24 20:14:13 +0200237 uint8_t tmp[160];
238 uint8_t septet_data[256];
239 uint8_t ud_header[6];
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200240 int nchars;
Harald Welteec8b4502010-02-20 20:34:29 +0100241 char result[256];
242
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800243 /* test 7-bit encoding */
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200244 for (i = 0; i < ARRAY_SIZE(test_encode); ++i) {
245 memset(coded, 0x42, sizeof(coded));
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200246 septet_length = gsm_7bit_encode_n(coded, sizeof(coded),
247 (const char *) test_encode[i].input,
248 &octets_written);
249 computed_octet_length = gsm_get_octet_len(septet_length);
250 printf("Encode case %d: "
251 "Octet length %d (expected %d, computed %d), "
252 "septet length %d (expected %d)\n"
253 , i
254 , octets_written, test_encode[i].expected_octet_length, computed_octet_length
255 , septet_length, test_encode[i].expected_septet_length
256 );
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800257
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200258 OSMO_ASSERT (octets_written == test_encode[i].expected_octet_length);
259 OSMO_ASSERT (octets_written == computed_octet_length);
260 OSMO_ASSERT (memcmp(coded, test_encode[i].expected, octets_written) == 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200261
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200262 /* check buffer limiting */
263 memset(coded, 0xaa, sizeof(coded));
264
265 for (buffer_size = 0;
266 buffer_size < test_encode[i].expected_octet_length + 1
267 && buffer_size < sizeof(coded) - 1;
268 ++buffer_size)
269 {
270 gsm_7bit_encode_n(coded, buffer_size,
271 (const char *) test_encode[i].input,
272 &octets_written);
273
274 OSMO_ASSERT(octets_written <= buffer_size);
275 OSMO_ASSERT(coded[buffer_size] == 0xaa);
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800276 }
Harald Welteec8b4502010-02-20 20:34:29 +0100277 }
Nico Golde28de0532010-07-09 17:19:12 +0200278
Dennis Wehrle291e6132011-07-24 20:14:13 +0200279
280 /* Test: encode multiple SMS */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200281 int number_of_septets = gsm_septet_encode(septet_data, (const char *) test_multiple_encode[0].input);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200282
283 /* SMS part 1 */
284 memset(tmp, 0x42, sizeof(tmp));
285 memset(coded, 0x42, sizeof(coded));
286 memcpy(tmp, septet_data, concatenated_part1_septet_length);
287
288 /* In our case: test_multiple_decode[0].ud_hdr_ind equals number of padding bits*/
289 octet_length = gsm_septets2octets(coded, tmp, concatenated_part1_septet_length, test_multiple_encode[0].ud_hdr_ind);
290
291 /* copy header */
292 memset(tmp, 0x42, sizeof(tmp));
293 int udh_length = test_multiple_encode[0].expected[0] + 1;
294 memcpy(tmp, test_multiple_encode[0].expected, udh_length);
295 memcpy(tmp + udh_length, coded, octet_length);
296 memset(coded, 0x42, sizeof(coded));
297 memcpy(coded, tmp, octet_length + 6);
298
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200299 OSMO_ASSERT(memcmp(coded, test_multiple_encode[0].expected, octet_length) == 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200300
301 /* SMS part 2 */
302 memset(tmp, 0x42, sizeof(tmp));
303 memset(coded, 0x42, sizeof(coded));
304 memcpy(tmp, septet_data + concatenated_part1_septet_length, concatenated_part2_septet_length);
305
306 /* In our case: test_multiple_decode[1].ud_hdr_ind equals number of padding bits*/
307 octet_length = gsm_septets2octets(coded, tmp, concatenated_part2_septet_length, test_multiple_encode[1].ud_hdr_ind);
308
309 /* copy header */
310 memset(tmp, 0x42, sizeof(tmp));
311 udh_length = test_multiple_encode[1].expected[0] + 1;
312 memcpy(tmp, test_multiple_encode[1].expected, udh_length);
313 memcpy(tmp + udh_length, coded, octet_length);
314 memset(coded, 0x42, sizeof(coded));
315 memcpy(coded, tmp, octet_length + 6);
316
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200317 OSMO_ASSERT(memcmp(coded, test_multiple_encode[1].expected, octet_length) == 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200318
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800319 /* test 7-bit decoding */
320 for (i = 0; i < ARRAY_SIZE(test_decode); ++i) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200321 memset(result, 0x42, sizeof(result));
322 nchars = gsm_7bit_decode_n_hdr(result, sizeof(result), test_decode[i].input,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200323 test_decode[i].expected_septet_length, test_decode[i].ud_hdr_ind);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200324 printf("Decode case %d: return value %d (expected %d)\n", i, nchars, strlen(result));
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800325
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200326 OSMO_ASSERT(strcmp(result, (const char *) test_decode[i].expected) == 0);
327 OSMO_ASSERT(nchars == strlen(result));
328
329 /* check buffer limiting */
330 memset(result, 0xaa, sizeof(result));
331
332 for (buffer_size = 1;
333 buffer_size < test_encode[i].expected_septet_length + 1
334 && buffer_size < sizeof(result) - 1;
335 ++buffer_size)
336 {
337 nchars = gsm_7bit_decode_n_hdr(result, buffer_size, test_decode[i].input,
338 test_decode[i].expected_septet_length, test_decode[i].ud_hdr_ind);
339
340 OSMO_ASSERT(nchars <= buffer_size);
341 OSMO_ASSERT(result[buffer_size] == (char)0xaa);
342 OSMO_ASSERT(result[nchars] == '\0');
Dennis Wehrle291e6132011-07-24 20:14:13 +0200343 }
Nico Golde28de0532010-07-09 17:19:12 +0200344 }
345
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200346 test_octet_return();
347
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800348 printf("OK\n");
Nico Golde28de0532010-07-09 17:19:12 +0200349 return 0;
Harald Welteec8b4502010-02-20 20:34:29 +0100350}