blob: 6df4b62365d2e40efb8ec09f397f4b5de215c87d [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 {
119 .input = concatenated_text,
120 .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 {
126 .input = concatenated_text,
127 .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 {
137 .input = simple_text,
138 .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 {
144 .input = escape_text,
145 .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 {
151 .input = enhanced_text,
152 .expected = enhanced_enc,
153 .expected_octet_length = sizeof(enhanced_enc),
154 .expected_septet_length = enhanced_septet_length,
155 .ud_hdr_ind = 0,
156 },
157 {
158 .input = enhancedV2_text,
159 .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),
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800171 .expected = 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),
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800178 .expected = 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),
185 .expected = enhanced_text,
186 .expected_septet_length = enhanced_septet_length,
187 .ud_hdr_ind = 0,
188 },
189 {
190 .input = enhancedV2_enc,
191 .input_length = sizeof(enhancedV2_enc),
192 .expected = enhancedV2_text,
193 .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),
199 .expected = splitted_text_part1,
200 .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),
206 .expected = splitted_text_part2,
207 .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
212int main(int argc, char** argv)
213{
214 printf("SMS testing\n");
215 struct msgb *msg;
Harald Welteec8b4502010-02-20 20:34:29 +0100216 uint8_t i;
217
Dennis Wehrle291e6132011-07-24 20:14:13 +0200218 uint8_t octet_length;
219 uint8_t septet_length;
220 uint8_t gsm_septet_length;
Harald Welteec8b4502010-02-20 20:34:29 +0100221 uint8_t coded[256];
Dennis Wehrle291e6132011-07-24 20:14:13 +0200222 uint8_t tmp[160];
223 uint8_t septet_data[256];
224 uint8_t ud_header[6];
Harald Welteec8b4502010-02-20 20:34:29 +0100225 char result[256];
226
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800227 /* test 7-bit encoding */
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200228 for (i = 0; i < ARRAY_SIZE(test_encode); ++i) {
229 memset(coded, 0x42, sizeof(coded));
Dennis Wehrle291e6132011-07-24 20:14:13 +0200230 septet_length = gsm_7bit_encode(coded, test_encode[i].input);
231 octet_length = gsm_get_octet_len(septet_length);
232 if (octet_length != test_encode[i].expected_octet_length) {
233 fprintf(stderr, "Encode case %d: Octet length failure. Got %d, expected %d\n",
234 i, octet_length, test_encode[i].expected_octet_length);
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800235 return -1;
236 }
237
Dennis Wehrle291e6132011-07-24 20:14:13 +0200238 if (septet_length != test_encode[i].expected_septet_length){
239 fprintf(stderr, "Encode case %d: Septet length failure. Got %d, expected %d\n",
240 i, septet_length, test_encode[i].expected_septet_length);
241 return -1;
242 }
243
244 if (memcmp(coded, test_encode[i].expected, octet_length) != 0) {
245 fprintf(stderr, "Encoded content does not match for case %d\n",
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800246 i);
247 return -1;
248 }
Harald Welteec8b4502010-02-20 20:34:29 +0100249 }
Nico Golde28de0532010-07-09 17:19:12 +0200250
Dennis Wehrle291e6132011-07-24 20:14:13 +0200251
252 /* Test: encode multiple SMS */
253 int number_of_septets = gsm_septet_encode(septet_data, test_multiple_encode[0].input);
254
255 /* SMS part 1 */
256 memset(tmp, 0x42, sizeof(tmp));
257 memset(coded, 0x42, sizeof(coded));
258 memcpy(tmp, septet_data, concatenated_part1_septet_length);
259
260 /* In our case: test_multiple_decode[0].ud_hdr_ind equals number of padding bits*/
261 octet_length = gsm_septets2octets(coded, tmp, concatenated_part1_septet_length, test_multiple_encode[0].ud_hdr_ind);
262
263 /* copy header */
264 memset(tmp, 0x42, sizeof(tmp));
265 int udh_length = test_multiple_encode[0].expected[0] + 1;
266 memcpy(tmp, test_multiple_encode[0].expected, udh_length);
267 memcpy(tmp + udh_length, coded, octet_length);
268 memset(coded, 0x42, sizeof(coded));
269 memcpy(coded, tmp, octet_length + 6);
270
271 if (memcmp(coded, test_multiple_encode[0].expected, octet_length) != 0) {
272 fprintf(stderr, "Multiple-SMS encoded content does not match for part 1\n");
273 return -1;
274 }
275
276
277 /* SMS part 2 */
278 memset(tmp, 0x42, sizeof(tmp));
279 memset(coded, 0x42, sizeof(coded));
280 memcpy(tmp, septet_data + concatenated_part1_septet_length, concatenated_part2_septet_length);
281
282 /* In our case: test_multiple_decode[1].ud_hdr_ind equals number of padding bits*/
283 octet_length = gsm_septets2octets(coded, tmp, concatenated_part2_septet_length, test_multiple_encode[1].ud_hdr_ind);
284
285 /* copy header */
286 memset(tmp, 0x42, sizeof(tmp));
287 udh_length = test_multiple_encode[1].expected[0] + 1;
288 memcpy(tmp, test_multiple_encode[1].expected, udh_length);
289 memcpy(tmp + udh_length, coded, octet_length);
290 memset(coded, 0x42, sizeof(coded));
291 memcpy(coded, tmp, octet_length + 6);
292
293 if (memcmp(coded, test_multiple_encode[1].expected, octet_length) != 0) {
294 fprintf(stderr, "Multiple-SMS encoded content does not match for part 2\n");
295 return -1;
296 }
297
298
299
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800300 /* test 7-bit decoding */
301 for (i = 0; i < ARRAY_SIZE(test_decode); ++i) {
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200302 memset(result, 0x42, sizeof(coded));
Dennis Wehrle291e6132011-07-24 20:14:13 +0200303 septet_length = gsm_7bit_decode_hdr(result, test_decode[i].input,
304 test_decode[i].expected_septet_length, test_decode[i].ud_hdr_ind);
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800305
306 if (strcmp(result, test_decode[i].expected) != 0) {
307 fprintf(stderr, "Test case %d failed to decode.\n", i);
308 return -1;
309 }
Dennis Wehrle291e6132011-07-24 20:14:13 +0200310 if (septet_length != test_decode[i].expected_septet_length) {
311 fprintf(stderr, "Decode case %d: Septet length failure. Got %d, expected %d\n",
312 i, septet_length, test_decode[i].expected_septet_length);
313 return -1;
314 }
Nico Golde28de0532010-07-09 17:19:12 +0200315 }
316
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800317 printf("OK\n");
Nico Golde28de0532010-07-09 17:19:12 +0200318 return 0;
Harald Welteec8b4502010-02-20 20:34:29 +0100319}