Upgrade ofono to 1.2
[profile/ivi/ofono.git] / unit / test-mux.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
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
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32
33 #include <glib.h>
34 #include <glib/gprintf.h>
35
36 #include "gatmux.h"
37 #include "gsm0710.h"
38
39 static int do_connect(const char *address, unsigned short port)
40 {
41         struct sockaddr_in addr;
42         int sk, err;
43
44         sk = socket(PF_INET, SOCK_STREAM, 0);
45         if (sk < 0)
46                 return sk;
47
48         memset(&addr, 0, sizeof(addr));
49         addr.sin_family = AF_INET;
50         addr.sin_addr.s_addr = inet_addr(address);
51         addr.sin_port = htons(port);
52
53         err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
54         if (err < 0) {
55                 close(sk);
56                 return err;
57         }
58
59         return sk;
60 }
61
62 static GMainLoop *mainloop;
63 static GAtMux *mux;
64
65 static gboolean cleanup_callback(gpointer data)
66 {
67         g_at_mux_unref(mux);
68
69         g_main_loop_quit(mainloop);
70
71         return FALSE;
72 }
73
74 static gboolean chat_cleanup(gpointer data)
75 {
76         GAtChat *chat = data;
77
78         g_at_chat_unref(chat);
79
80         return FALSE;
81 }
82
83 static void chat_callback(gboolean ok, GAtResult *result, gpointer user_data)
84 {
85         GAtResultIter iter;
86
87         g_at_result_iter_init(&iter, result);
88
89         g_print("chat: callback [ok %d]\n", ok);
90
91         g_print("%s\n", g_at_result_final_response(result));
92
93         g_idle_add(chat_cleanup, user_data);
94 }
95
96 static void mux_debug(const char *str, void *data)
97 {
98         g_print("%s: %s\n", (char *) data, str);
99 }
100
101 static void mux_setup(GAtMux *m, gpointer data)
102 {
103         GAtChat *chat = data;
104         GIOChannel *io;
105         GAtSyntax *syntax;
106
107         mux = m;
108
109         g_print("mux_setup: %p\n", mux);
110
111         if (mux == NULL) {
112                 g_at_chat_unref(chat);
113                 g_main_loop_quit(mainloop);
114                 return;
115         }
116
117         g_at_mux_start(mux);
118
119         io = g_at_mux_create_channel(mux);
120         syntax = g_at_syntax_new_gsm_permissive();
121         chat = g_at_chat_new(io, syntax);
122         g_at_syntax_unref(syntax);
123         g_io_channel_unref(io);
124
125         g_at_chat_set_debug(chat, mux_debug, "CHAT1");
126         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
127         g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
128         g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
129
130         io = g_at_mux_create_channel(mux);
131         syntax = g_at_syntax_new_gsm_permissive();
132         chat = g_at_chat_new(io, syntax);
133         g_at_syntax_unref(syntax);
134         g_io_channel_unref(io);
135
136         g_at_chat_set_debug(chat, mux_debug, "CHAT2");
137         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
138         g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
139         g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
140
141         io = g_at_mux_create_channel(mux);
142         syntax = g_at_syntax_new_gsm_permissive();
143         chat = g_at_chat_new(io, syntax);
144         g_at_syntax_unref(syntax);
145         g_io_channel_unref(io);
146
147         g_at_chat_set_debug(chat, mux_debug, "CHAT3");
148         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
149         g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
150         g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
151
152         io = g_at_mux_create_channel(mux);
153         syntax = g_at_syntax_new_gsm_permissive();
154         chat = g_at_chat_new(io, syntax);
155         g_at_syntax_unref(syntax);
156         g_io_channel_unref(io);
157
158         g_at_chat_set_debug(chat, mux_debug, "CHAT4");
159         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
160         g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
161         g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
162
163         g_timeout_add_seconds(7, cleanup_callback, NULL);
164 }
165
166 static void mux_init(gboolean ok, GAtResult *result, gpointer data)
167 {
168         GAtChat *chat = data;
169
170         g_print("mux_init: %d\n", ok);
171
172         if (ok == FALSE) {
173                 g_at_chat_unref(chat);
174                 g_main_loop_quit(mainloop);
175                 return;
176         }
177
178         g_at_mux_setup_gsm0710(chat, mux_setup, chat, NULL);
179 }
180
181 static void test_mux(void)
182 {
183         GIOChannel *io;
184         GAtChat *chat;
185         GAtSyntax *syntax;
186         int sk;
187
188         sk = do_connect("192.168.0.202", 2000);
189         if (sk < 0) {
190                 g_printerr("connect failed\n");
191                 return;
192         }
193
194         mux = NULL;
195         io = g_io_channel_unix_new(sk);
196         g_io_channel_set_close_on_unref(io, TRUE);
197
198         syntax = g_at_syntax_new_gsm_permissive();
199         chat = g_at_chat_new(io, syntax);
200         g_at_syntax_unref(syntax);
201
202         g_io_channel_unref(io);
203
204         if (chat == NULL) {
205                 g_printerr("Chat creation failed\n");
206                 return;
207         }
208
209         g_at_chat_set_debug(chat, mux_debug, "MUX");
210         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
211         g_at_chat_send(chat, "ATE0", NULL, mux_init, chat, NULL);
212
213         mainloop = g_main_loop_new(NULL, FALSE);
214
215         g_main_loop_run(mainloop);
216         g_main_loop_unref(mainloop);
217 }
218
219 static void test_basic(void)
220 {
221         if (g_test_trap_fork(60 * 1000 * 1000, 0) == TRUE) {
222                 test_mux();
223                 exit(0);
224         }
225
226         g_test_trap_assert_passed();
227         //g_test_trap_assert_stderr("failed");
228 }
229
230 /* DLC 1, Open Channel */
231 static const guint8 basic_open[] = { 0xF9, 0x07, 0x3F, 0x01, 0xDE, 0xF9 };
232
233 /* DLC 1, Close Channel */
234 static char const basic_close[] = { 0xF9, 0x07, 0x53, 0x01, 0x3F, 0xF9 };
235
236 /* DLC 1, Data */
237 static const guint8 basic_data[] = { 0x12, 0x34, 0x56 };
238 static const guint8 basic_data_result[] =
239         { 0xF9, 0x07, 0xEF, 0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9 };
240
241 /* DLC 1, Long Data */
242 static const guint8 basic_long_frame[] =
243 {       0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
244         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
245         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
246         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
247         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
248         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
249         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
250         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
251         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
252         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
253         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
254         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
255         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
256         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
257         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
258         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
259         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
260 };
261
262 static const guint8 basic_long_frame_result[] =
263 {       0xF9, 0x07, 0xEF, 0x10, 0x01, 0x12, 0x34, 0x56,
264         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
265         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
266         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
267         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
268         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
269         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
270         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
271         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
272         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
273         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
274         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
275         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
276         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
277         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
278         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
279         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
280         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x88, 0xF9
281 };
282
283 static void test_fill_basic(void)
284 {
285         guint8 control_frame[6];
286         guint8 data_frame[128];
287         guint8 long_frame[256];
288         int s;
289
290         s = gsm0710_basic_fill_frame(control_frame, 1, GSM0710_OPEN_CHANNEL,
291                                         NULL, 0);
292         g_assert(s == sizeof(basic_open));
293         g_assert(memcmp(basic_open, control_frame, s) == 0);
294
295         s = gsm0710_basic_fill_frame(control_frame, 1, GSM0710_CLOSE_CHANNEL,
296                                         NULL, 0);
297         g_assert(s == sizeof(basic_close));
298         g_assert(memcmp(basic_close, control_frame, s) == 0);
299
300         s = gsm0710_basic_fill_frame(data_frame, 1, GSM0710_DATA,
301                                         basic_data, sizeof(basic_data));
302         g_assert(s == sizeof(basic_data_result));
303         g_assert(memcmp(basic_data_result, data_frame, s) == 0);
304
305         s = gsm0710_basic_fill_frame(long_frame, 1, GSM0710_DATA,
306                                         basic_long_frame,
307                                         sizeof(basic_long_frame));
308         g_assert(s == sizeof(basic_long_frame_result));
309         g_assert(memcmp(basic_long_frame_result, long_frame, s) == 0);
310 }
311
312 /* DLC 1, Open Channel */
313 static const guint8 advanced_open[] = { 0x7E, 0x07, 0x3F, 0x89, 0x7E };
314
315 /* DLC 1, Close Channel */
316 static const guint8 advanced_close[] = { 0x7E, 0x07, 0x53, 0xC8, 0x7E };
317
318 /* DLC 1, Data */
319 static const guint8 advanced_data[] = { 0x12, 0x34, 0x56 };
320 static const guint8 advanced_data_result[] =
321         { 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
322
323 /* DLC 1, Quoted data */
324 static const guint8 advanced_quoted_data[] =
325         { 0x12, 0x34, 0x56, 0x7E, 0x78, 0x7D };
326 static const guint8 advanced_quoted_data_result[] =
327         { 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x7D, 0x5E, 0x78,
328                 0x7D, 0x5D, 0x05, 0x7E };
329
330 static void test_fill_advanced(void)
331 {
332         guint8 control_frame[8];
333         guint8 data_frame[128];
334         int s;
335
336         s = gsm0710_advanced_fill_frame(control_frame, 1, GSM0710_OPEN_CHANNEL,
337                                         NULL, 0);
338         g_assert(s == sizeof(advanced_open));
339         g_assert(memcmp(advanced_open, control_frame, s) == 0);
340
341         s = gsm0710_advanced_fill_frame(control_frame, 1, GSM0710_CLOSE_CHANNEL,
342                                         NULL, 0);
343         g_assert(s == sizeof(advanced_close));
344         g_assert(memcmp(advanced_close, control_frame, s) == 0);
345
346         s = gsm0710_advanced_fill_frame(data_frame, 1, GSM0710_DATA,
347                                         advanced_data, sizeof(advanced_data));
348         g_assert(s == sizeof(advanced_data_result));
349         g_assert(memcmp(advanced_data_result, data_frame, s) == 0);
350
351         s = gsm0710_advanced_fill_frame(data_frame, 1, GSM0710_DATA,
352                                         advanced_quoted_data,
353                                         sizeof(advanced_quoted_data));
354         g_assert(s == sizeof(advanced_quoted_data_result));
355         g_assert(memcmp(advanced_quoted_data_result, data_frame, s) == 0);
356 }
357
358 static guint8 basic_input[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x07, 0xEF,
359         0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9, 0x07, 0xEF, 0x07, 0x12, 0x34, 0x56,
360         0xD3, 0xF9 };
361
362 static guint8 basic_input2[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x07, 0xEF,
363         0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9, 0xF9, 0x07, 0xEF, 0x07, 0x12,
364         0x34, 0x56, 0xD3, 0xF9 };
365
366 static int basic_garbage_size = 4;
367 static int basic_frame_size = 7;
368
369 static const guint8 basic_output[] = { 0x12, 0x34, 0x56 };
370
371 static void test_extract_basic(void)
372 {
373         int total = 0;
374         int nread;
375         guint8 dlc;
376         guint8 ctrl;
377         guint8 *frame;
378         int frame_size;
379
380         frame = NULL;
381         frame_size = 0;
382
383         nread = gsm0710_basic_extract_frame(basic_input + total,
384                                                 basic_garbage_size, &dlc, &ctrl,
385                                                 &frame, &frame_size);
386
387         g_assert(frame == NULL);
388         g_assert(frame_size == 0);
389
390         total += nread;
391
392         /* Try to read with just the open flag */
393         nread = gsm0710_basic_extract_frame(basic_input + total,
394                                                 basic_frame_size + 1,
395                                                 &dlc, &ctrl,
396                                                 &frame, &frame_size);
397
398         g_assert(nread == 0);
399         g_assert(frame == NULL);
400
401         /* Now read with the close flag as well */
402         nread = gsm0710_basic_extract_frame(basic_input + total,
403                                                 basic_frame_size + 2,
404                                                 &dlc, &ctrl,
405                                                 &frame, &frame_size);
406
407         /* Extracted the open flag + frame */
408         g_assert(nread == basic_frame_size + 1);
409         g_assert(frame_size == sizeof(basic_output));
410         g_assert(memcmp(basic_output, frame, frame_size) == 0);
411
412         total += nread;
413
414         nread = gsm0710_basic_extract_frame(basic_input + total,
415                                                 sizeof(basic_input) - total,
416                                                 &dlc, &ctrl,
417                                                 &frame, &frame_size);
418
419         g_assert(nread == (int)(sizeof(basic_input) - total - 1));
420         g_assert(frame_size == sizeof(basic_output));
421         g_assert(memcmp(basic_output, frame, frame_size) == 0);
422
423         total += nread;
424
425         nread = gsm0710_basic_extract_frame(basic_input + total,
426                                                 sizeof(basic_input) - total,
427                                                 &dlc, &ctrl,
428                                                 &frame, &frame_size);
429         g_assert(nread == 0);
430
431         total = 0;
432
433         nread = gsm0710_basic_extract_frame(basic_input2 + total,
434                                                 sizeof(basic_input2) - total,
435                                                 &dlc, &ctrl,
436                                                 &frame, &frame_size);
437
438         g_assert(nread == basic_garbage_size + basic_frame_size + 1);
439         g_assert(frame_size == sizeof(basic_output));
440         g_assert(memcmp(basic_output, frame, frame_size) == 0);
441
442         total += nread;
443
444         nread = gsm0710_basic_extract_frame(basic_input2 + total,
445                                                 sizeof(basic_input2) - total,
446                                                 &dlc, &ctrl,
447                                                 &frame, &frame_size);
448
449         g_assert(frame_size == sizeof(basic_output));
450         g_assert(memcmp(basic_output, frame, frame_size) == 0);
451
452         total += nread;
453
454         g_assert(total == sizeof(basic_input2) - 1);
455 }
456
457 static guint8 advanced_input[] =
458         { 0xFF, 0xFF, 0xFF, 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E,
459                 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
460
461 static guint8 advanced_input2[] =
462         { 0xFF, 0xFF, 0xFF, 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E,
463                 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
464
465 static int advanced_garbage_size = 3;
466 static int advanced_frame_size = 6;
467
468 static const guint8 advanced_output[] = { 0x12, 0x34, 0x56 };
469
470 static void test_extract_advanced(void)
471 {
472         int total = 0;
473         int nread;
474         guint8 dlc;
475         guint8 ctrl;
476         guint8 *frame;
477         int frame_size;
478
479         frame = NULL;
480         frame_size = 0;
481
482         nread = gsm0710_advanced_extract_frame(advanced_input + total,
483                                                 advanced_garbage_size,
484                                                 &dlc, &ctrl,
485                                                 &frame, &frame_size);
486
487         g_assert(frame == NULL);
488         g_assert(frame_size == 0);
489
490         total += nread;
491
492         /* Try to read with just the open flag */
493         nread = gsm0710_advanced_extract_frame(advanced_input + total,
494                                                 advanced_frame_size + 1,
495                                                 &dlc, &ctrl,
496                                                 &frame, &frame_size);
497
498         g_assert(nread == 0);
499         g_assert(frame == NULL);
500
501         /* Now read with the close flag as well */
502         nread = gsm0710_advanced_extract_frame(advanced_input + total,
503                                                 advanced_frame_size + 2,
504                                                 &dlc, &ctrl,
505                                                 &frame, &frame_size);
506
507         /* Extracted the open flag + frame */
508         g_assert(nread == advanced_frame_size + 1);
509         g_assert(frame_size == sizeof(advanced_output));
510         g_assert(memcmp(advanced_output, frame, frame_size) == 0);
511
512         total += nread;
513
514         nread = gsm0710_advanced_extract_frame(advanced_input + total,
515                                                 sizeof(advanced_input) - total,
516                                                 &dlc, &ctrl,
517                                                 &frame, &frame_size);
518
519         g_assert(nread == (int)(sizeof(advanced_input) - total - 1));
520         g_assert(frame_size == sizeof(advanced_output));
521         g_assert(memcmp(advanced_output, frame, frame_size) == 0);
522
523         total += nread;
524
525         nread = gsm0710_advanced_extract_frame(advanced_input + total,
526                                                 sizeof(advanced_input) - total,
527                                                 &dlc, &ctrl,
528                                                 &frame, &frame_size);
529         g_assert(nread == 0);
530
531         total = 0;
532
533         nread = gsm0710_advanced_extract_frame(advanced_input2 + total,
534                                                 sizeof(advanced_input2) - total,
535                                                 &dlc, &ctrl,
536                                                 &frame, &frame_size);
537
538         g_assert(nread == advanced_garbage_size + advanced_frame_size + 1);
539         g_assert(frame_size == sizeof(advanced_output));
540         g_assert(memcmp(advanced_output, frame, frame_size) == 0);
541
542         total += nread;
543
544         nread = gsm0710_advanced_extract_frame(advanced_input2 + total,
545                                                 sizeof(advanced_input2) - total,
546                                                 &dlc, &ctrl,
547                                                 &frame, &frame_size);
548
549         g_assert(frame_size == sizeof(advanced_output));
550         g_assert(memcmp(advanced_output, frame, frame_size) == 0);
551
552         total += nread;
553
554         g_assert(total == sizeof(advanced_input2) - 1);
555 }
556
557 int main(int argc, char **argv)
558 {
559         g_test_init(&argc, &argv, NULL);
560
561         g_test_add_func("/testmux/fill_basic", test_fill_basic);
562         g_test_add_func("/testmux/fill_advanced", test_fill_advanced);
563         g_test_add_func("/testmux/extract_basic", test_extract_basic);
564         g_test_add_func("/testmux/extract_advanced", test_extract_advanced);
565         g_test_add_func("/testmux/basic", test_basic);
566
567         return g_test_run();
568 }