Upgrade ofono to 1.2
[profile/ivi/ofono.git] / gatchat / test-server.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 <stdio.h>
28 #include <getopt.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/socket.h>
33 #include <sys/un.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <signal.h>
37 #include <sys/signalfd.h>
38 #include <errno.h>
39
40 #include <glib.h>
41 #include <utmp.h>
42 #include <pty.h>
43
44 #include <sys/types.h>
45 #include <sys/stat.h>
46
47 #include "gatserver.h"
48 #include "gatppp.h"
49 #include "ringbuffer.h"
50
51 #define DEFAULT_TCP_PORT 12346
52 #define DEFAULT_SOCK_PATH "./server_sock"
53 #define IFCONFIG_PATH "/sbin/ifconfig"
54
55 static gboolean data_mode = FALSE;
56 static int modem_mode = 0;
57 static int modem_creg = 0;
58 static int modem_cgreg = 0;
59 static int network_status = 4;
60 static int network_attach = 0;
61
62 struct sock_server{
63         int server_sock;
64 };
65
66 static GMainLoop *mainloop;
67 static GAtServer *main_server;
68 static GAtPPP *ppp;
69 unsigned int server_watch;
70
71 static gboolean server_cleanup(void)
72 {
73         if (server_watch)
74                 g_source_remove(server_watch);
75
76         if (ppp) {
77                 g_at_ppp_unref(ppp);
78                 ppp = NULL;
79         }
80
81         g_at_server_unref(main_server);
82         main_server = NULL;
83
84         unlink(DEFAULT_SOCK_PATH);
85
86         g_main_loop_quit(mainloop);
87
88         return FALSE;
89 }
90
91 static void server_debug(const char *str, void *data)
92 {
93         g_print("%s: %s\n", (char *) data, str);
94 }
95
96 static gboolean execute(const char *cmd)
97 {
98         int status;
99
100         status = system(cmd);
101         if (status < 0) {
102                 g_print("Failed to execute command: %s\n", strerror(errno));
103                 return FALSE;
104         }
105
106         return TRUE;
107 }
108
109 static void ppp_connect(const char *iface, const char *local, const char *peer,
110                         const char *dns1, const char *dns2,
111                         gpointer user)
112 {
113         char buf[512];
114
115         g_print("Network Device: %s\n", iface);
116         g_print("IP Address: %s\n", local);
117         g_print("Peer IP Address: %s\n", peer);
118         g_print("Primary DNS Server: %s\n", dns1);
119         g_print("Secondary DNS Server: %s\n", dns2);
120
121         snprintf(buf, sizeof(buf), "%s %s up", IFCONFIG_PATH, iface);
122         execute(buf);
123
124         snprintf(buf, sizeof(buf), "%s %s %s pointopoint %s", IFCONFIG_PATH,
125                                 iface, local, peer);
126         execute(buf);
127
128         snprintf(buf, sizeof(buf), "echo 1 > /proc/sys/net/ipv4/ip_forward");
129         execute(buf);
130 }
131
132 static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user)
133 {
134         GAtServer *server = user;
135
136         g_print("PPP Link down: %d\n", reason);
137
138         g_at_ppp_unref(ppp);
139         ppp = NULL;
140
141         if (reason == G_AT_PPP_REASON_LINK_DEAD) {
142                 g_at_server_unref(server);
143                 server = NULL;
144                 return;
145         }
146
147         g_at_server_resume(server);
148         g_at_server_set_debug(server, server_debug, "Server");
149
150         g_at_server_send_final(server, G_AT_SERVER_RESULT_NO_CARRIER);
151         data_mode = FALSE;
152 }
153
154 static void open_ppp(gpointer user)
155 {
156         GAtIO *io = g_at_server_get_io(main_server);
157
158         g_at_server_suspend(main_server);
159         g_at_ppp_listen(ppp, io);
160 }
161
162 static gboolean setup_ppp(GAtServer *server)
163 {
164         /* open ppp */
165         ppp = g_at_ppp_server_new("192.168.1.1");
166         if (ppp == NULL)
167                 return FALSE;
168
169         g_at_ppp_set_debug(ppp, server_debug, "PPP");
170
171         g_at_ppp_set_credentials(ppp, "", "");
172
173         /* set connect and disconnect callbacks */
174         g_at_ppp_set_connect_function(ppp, ppp_connect, server);
175         g_at_ppp_set_disconnect_function(ppp, ppp_disconnect, server);
176         g_at_ppp_set_server_info(ppp, "192.168.1.2",
177                                         "10.10.10.10", "10.10.10.11");
178
179         return TRUE;
180 }
181
182 static void cgmi_cb(GAtServer *server, GAtServerRequestType type,
183                         GAtResult *cmd, gpointer user)
184 {
185         switch (type) {
186         case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
187                 g_at_server_send_info(server, "oFono", TRUE);
188                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
189                 break;
190         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
191                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
192                 break;
193         default:
194                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
195         };
196 }
197
198 static void cgmm_cb(GAtServer *server, GAtServerRequestType type,
199                         GAtResult *cmd, gpointer user)
200 {
201         switch (type) {
202         case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
203                 g_at_server_send_info(server, "oFono pre-1.0", TRUE);
204                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
205                 break;
206         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
207                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
208                 break;
209         default:
210                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
211         };
212 }
213
214 static void cgmr_cb(GAtServer *server, GAtServerRequestType type,
215                         GAtResult *cmd, gpointer user)
216 {
217         char buf[256];
218
219         switch (type) {
220         case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
221                 sprintf(buf, "oFono pre-1.0 version: %s", VERSION);
222                 g_at_server_send_info(server, buf, TRUE);
223                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
224                 break;
225         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
226                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
227                 break;
228         default:
229                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
230         };
231 }
232
233 static void cgsn_cb(GAtServer *server, GAtServerRequestType type,
234                         GAtResult *cmd, gpointer user)
235 {
236         switch (type) {
237         case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
238                 g_at_server_send_info(server, "123456789", TRUE);
239                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
240                 break;
241         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
242                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
243                 break;
244         default:
245                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
246         };
247 }
248
249 static gboolean send_ok(gpointer user)
250 {
251         GAtServer *server = user;
252
253         g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
254
255         return FALSE;
256 }
257
258 static void cfun_cb(GAtServer *server, GAtServerRequestType type,
259                         GAtResult *cmd, gpointer user)
260 {
261         char buf[12];
262
263         switch (type) {
264         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
265                 g_at_server_send_info(server, "+CFUN: (0-1)", TRUE);
266                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
267                 break;
268         case G_AT_SERVER_REQUEST_TYPE_QUERY:
269                 snprintf(buf, sizeof(buf), "+CFUN: %d", modem_mode);
270                 g_at_server_send_info(server, buf, TRUE);
271                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
272                 break;
273         case G_AT_SERVER_REQUEST_TYPE_SET:
274         {
275                 GAtResultIter iter;
276                 int mode;
277
278                 g_at_result_iter_init(&iter, cmd);
279                 g_at_result_iter_next(&iter, "");
280
281                 if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
282                         goto error;
283
284                 if (mode != 0 && mode != 1)
285                         goto error;
286
287                 if (modem_mode == mode) {
288                         g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
289                         break;
290                 }
291
292                 modem_mode = mode;
293                 g_timeout_add_seconds(1, send_ok, server);
294                 break;
295         }
296         default:
297                 goto error;
298         };
299
300         return;
301
302 error:
303         g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
304 }
305
306 static void cpin_cb(GAtServer *server, GAtServerRequestType type,
307                         GAtResult *cmd, gpointer user)
308 {
309         if (modem_mode == 0) {
310                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
311                 return;
312         }
313
314         switch (type) {
315         case G_AT_SERVER_REQUEST_TYPE_SET:
316                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
317                 break;
318         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
319                 g_at_server_send_info(server, "+CPIN: (READY)", TRUE);
320                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
321                 break;
322         case G_AT_SERVER_REQUEST_TYPE_QUERY:
323                 g_at_server_send_info(server, "+CPIN: READY", TRUE);
324                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
325                 break;
326         default:
327                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
328                 break;
329         }
330 }
331
332 static gboolean do_netreg(gpointer user)
333 {
334         GAtServer *server = user;
335         char buf[32];
336
337         if (data_mode)
338                 return FALSE;
339
340         network_status = 1;
341
342         switch (modem_creg) {
343         case 1:
344         case 2:
345                 snprintf(buf, sizeof(buf), "+CREG: %d", network_status);
346                 g_at_server_send_unsolicited(server, buf);
347                 break;
348         }
349
350         return FALSE;
351 }
352
353 static void cops_cb(GAtServer *server, GAtServerRequestType type,
354                         GAtResult *cmd, gpointer user)
355 {
356         if (modem_mode == 0) {
357                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
358                 return;
359         }
360
361         switch (type) {
362         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
363                 g_timeout_add_seconds(3, send_ok, server);
364                 break;
365         case G_AT_SERVER_REQUEST_TYPE_QUERY:
366                 g_at_server_send_info(server, "+COPS: 0", TRUE);
367                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
368                 break;
369         case G_AT_SERVER_REQUEST_TYPE_SET:
370         {
371                 GAtServerResult result;
372                 GAtResultIter iter;
373                 int mode;
374
375                 g_at_result_iter_init(&iter, cmd);
376                 g_at_result_iter_next(&iter, "");
377
378                 if (g_at_result_iter_next_number(&iter, &mode) == TRUE) {
379                         if (mode == 0) {
380                                 g_timeout_add_seconds(2, do_netreg, server);
381                                 result = G_AT_SERVER_RESULT_OK;
382                         } else
383                                 result = G_AT_SERVER_RESULT_ERROR;
384                 } else
385                         result = G_AT_SERVER_RESULT_ERROR;
386
387                 g_at_server_send_final(server, result);
388                 break;
389         }
390         default:
391                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
392                 break;
393         }
394 }
395
396 static void creg_cb(GAtServer *server, GAtServerRequestType type,
397                         GAtResult *cmd, gpointer user)
398 {
399         char buf[20];
400
401         if (modem_mode == 0) {
402                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
403                 return;
404         }
405
406         switch (type) {
407         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
408                 g_at_server_send_info(server, "+CREG: (0-2)", TRUE);
409                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
410                 break;
411         case G_AT_SERVER_REQUEST_TYPE_QUERY:
412                 snprintf(buf, sizeof(buf), "+CREG: %d,%d",
413                                                 modem_creg, network_status);
414                 g_at_server_send_info(server, buf, TRUE);
415                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
416                 break;
417         case G_AT_SERVER_REQUEST_TYPE_SET:
418         {
419                 GAtResultIter iter;
420                 int mode;
421
422                 g_at_result_iter_init(&iter, cmd);
423                 g_at_result_iter_next(&iter, "");
424
425                 if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
426                         goto error;
427
428                 if (mode != 0 && mode != 1 && mode != 2)
429                         goto error;
430
431                 modem_creg = mode;
432                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
433                 break;
434         }
435         default:
436                 goto error;
437         };
438
439         return;
440
441 error:
442         g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
443 }
444
445 static void cgreg_cb(GAtServer *server, GAtServerRequestType type,
446                         GAtResult *cmd, gpointer user)
447 {
448         char buf[20];
449
450         if (modem_mode == 0) {
451                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
452                 return;
453         }
454
455         switch (type) {
456         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
457                 g_at_server_send_info(server, "+CGREG: (0-2)", TRUE);
458                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
459                 break;
460         case G_AT_SERVER_REQUEST_TYPE_QUERY:
461                 snprintf(buf, sizeof(buf), "+CGREG: %d,%d",
462                                                 modem_cgreg, network_status);
463                 g_at_server_send_info(server, buf, TRUE);
464                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
465                 break;
466         case G_AT_SERVER_REQUEST_TYPE_SET:
467         {
468                 GAtResultIter iter;
469                 int mode;
470
471                 g_at_result_iter_init(&iter, cmd);
472                 g_at_result_iter_next(&iter, "");
473
474                 if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
475                         goto error;
476
477                 if (mode != 0 && mode != 1 && mode != 2)
478                         goto error;
479
480                 modem_cgreg = mode;
481                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
482                 break;
483         }
484         default:
485                 goto error;
486         };
487
488         return;
489
490 error:
491         g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
492 }
493
494 static void cgatt_cb(GAtServer *server, GAtServerRequestType type,
495                         GAtResult *cmd, gpointer user)
496 {
497         char buf[12];
498
499         if (modem_mode == 0) {
500                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
501                 return;
502         }
503
504         switch (type) {
505         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
506                 g_at_server_send_info(server, "+CGATT: (0-1)", TRUE);
507                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
508                 break;
509         case G_AT_SERVER_REQUEST_TYPE_QUERY:
510                 snprintf(buf, sizeof(buf), "+CGATT: %d", network_attach);
511                 g_at_server_send_info(server, buf, TRUE);
512                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
513                 break;
514         case G_AT_SERVER_REQUEST_TYPE_SET:
515         {
516                 GAtResultIter iter;
517                 int mode;
518
519                 g_at_result_iter_init(&iter, cmd);
520                 g_at_result_iter_next(&iter, "");
521
522                 if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
523                         goto error;
524
525                 if (mode != 0 && mode != 1)
526                         goto error;
527
528                 if (network_attach == mode) {
529                         g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
530                         break;
531                 }
532
533                 network_attach = mode;
534                 g_timeout_add_seconds(1, send_ok, server);
535                 break;
536         }
537         default:
538                 goto error;
539         };
540
541         return;
542
543 error:
544         g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
545 }
546
547 static void cgdata_cb(GAtServer *server, GAtServerRequestType type,
548                         GAtResult *cmd, gpointer user)
549 {
550         GAtIO *io;
551
552         if (modem_mode == 0) {
553                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
554                 return;
555         }
556
557         switch (type) {
558         case G_AT_SERVER_REQUEST_TYPE_SET:
559                 if (setup_ppp(server) == FALSE)
560                         goto error;
561
562                 g_at_server_send_intermediate(server, "CONNECT");
563                 data_mode = TRUE;
564
565                 io = g_at_server_get_io(server);
566                 g_at_io_set_write_done(io, open_ppp, server);
567                 break;
568         default:
569 error:
570                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
571                 break;
572         }
573 }
574
575 static void cgdcont_cb(GAtServer *server, GAtServerRequestType type,
576                         GAtResult *cmd, gpointer user)
577 {
578         if (modem_mode == 0) {
579                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
580                 return;
581         }
582
583         switch (type) {
584         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
585                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
586                 break;
587         case G_AT_SERVER_REQUEST_TYPE_QUERY:
588                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
589                 break;
590         case G_AT_SERVER_REQUEST_TYPE_SET:
591                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
592                 break;
593         default:
594                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
595                 break;
596         }
597 }
598
599 static void cimi_cb(GAtServer *server, GAtServerRequestType type,
600                         GAtResult *cmd, gpointer user)
601 {
602         switch (type) {
603         case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
604                 g_at_server_send_info(server, "246813579", TRUE);
605                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
606                 break;
607         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
608                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
609                 break;
610         default:
611                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
612                 break;
613         }
614 }
615
616 static void csms_cb(GAtServer *server, GAtServerRequestType type,
617                         GAtResult *cmd, gpointer user)
618 {
619         switch (type) {
620         case G_AT_SERVER_REQUEST_TYPE_SET:
621                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
622                 break;
623         case G_AT_SERVER_REQUEST_TYPE_QUERY:
624                 g_at_server_send_info(server, "+CSMS: 0,1,1,1", TRUE);
625                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
626                 break;
627         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
628                 g_at_server_send_info(server, "+CSMS: (0)", TRUE);
629                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
630                 break;
631         default:
632                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
633                 break;
634         }
635 }
636
637 static void cmgf_cb(GAtServer *server, GAtServerRequestType type,
638                         GAtResult *cmd, gpointer user)
639 {
640         switch (type) {
641         case G_AT_SERVER_REQUEST_TYPE_SET:
642                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
643                 break;
644         case G_AT_SERVER_REQUEST_TYPE_QUERY:
645                 g_at_server_send_info(server, "+CMGF: 0", TRUE);
646                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
647                 break;
648         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
649                 g_at_server_send_info(server, "+CMGF: (0,1)", TRUE);
650                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
651                 break;
652         default:
653                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
654                 break;
655         }
656 }
657
658 static void cpms_cb(GAtServer *server, GAtServerRequestType type,
659                         GAtResult *cmd, gpointer user)
660 {
661         char buf[2048];
662
663         switch (type) {
664         case G_AT_SERVER_REQUEST_TYPE_SET:
665                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
666                 break;
667         case G_AT_SERVER_REQUEST_TYPE_QUERY:
668                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
669                 break;
670         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
671                 sprintf(buf, "+CPMS: (\"SM\",\"ME\"),(\"SM\",\"ME\"),(\"SM\")");
672                 g_at_server_send_info(server, buf, TRUE);
673                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
674                 break;
675         default:
676                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
677                 break;
678         }
679 }
680
681 static void cnmi_cb(GAtServer *server, GAtServerRequestType type,
682                         GAtResult *cmd, gpointer user)
683 {
684         char buf[2048];
685
686         switch (type) {
687         case G_AT_SERVER_REQUEST_TYPE_SET:
688                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
689                 break;
690         case G_AT_SERVER_REQUEST_TYPE_QUERY:
691                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
692                 break;
693         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
694                 sprintf(buf, "+CNMI: (0,1,2,3),(0,1),(0,1,2),(0),(0,1)");
695                 g_at_server_send_info(server, buf, TRUE);
696                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
697                 break;
698         default:
699                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
700                 break;
701         }
702 }
703
704 static void cscs_cb(GAtServer *server, GAtServerRequestType type,
705                         GAtResult *cmd, gpointer user)
706 {
707         char buf[2048];
708
709         switch (type) {
710         case G_AT_SERVER_REQUEST_TYPE_SET:
711                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
712                 break;
713         case G_AT_SERVER_REQUEST_TYPE_QUERY:
714                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
715                 break;
716         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
717                 sprintf(buf, "+CSCS: \"GSM\",\"IRA\",\"UCS2\"");
718                 g_at_server_send_info(server, buf, TRUE);
719                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
720                 break;
721         default:
722                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
723                 break;
724         }
725 }
726
727 static void cmgl_cb(GAtServer *server, GAtServerRequestType type,
728                         GAtResult *cmd, gpointer user)
729 {
730         switch (type) {
731         case G_AT_SERVER_REQUEST_TYPE_SET:
732                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
733                 break;
734         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
735                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
736                 break;
737         default:
738                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
739                 break;
740         }
741 }
742
743 static void cpbs_cb(GAtServer *server, GAtServerRequestType type,
744                         GAtResult *cmd, gpointer user)
745 {
746         char buf[2048];
747
748         switch (type) {
749         case G_AT_SERVER_REQUEST_TYPE_SET:
750                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
751                 break;
752         case G_AT_SERVER_REQUEST_TYPE_QUERY:
753                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
754                 break;
755         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
756                 sprintf(buf, "+CPBS: (\"FD\",\"SM\",\"SN\")");
757                 g_at_server_send_info(server, buf, TRUE);
758                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
759                 break;
760         default:
761                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
762                 break;
763         }
764 }
765
766 static void dial_cb(GAtServer *server, GAtServerRequestType type,
767                         GAtResult *cmd, gpointer user)
768 {
769         GAtResultIter iter;
770         const char *dial_str;
771         char c;
772
773         if (type != G_AT_SERVER_REQUEST_TYPE_SET)
774                 goto error;
775
776         g_at_result_iter_init(&iter, cmd);
777         g_at_result_iter_next(&iter, "");
778
779         dial_str = g_at_result_iter_raw_line(&iter);
780         if (dial_str == NULL)
781                 goto error;
782
783         g_print("dial call %s\n", dial_str);
784
785         c = *dial_str;
786         if (c == '*' || c == '#' || c == 'T' || c == 't') {
787                 GAtIO *io = g_at_server_get_io(server);
788
789                 if (setup_ppp(server) == FALSE)
790                         goto error;
791
792                 g_at_server_send_intermediate(server, "CONNECT");
793                 data_mode = TRUE;
794                 g_at_io_set_write_done(io, open_ppp, server);
795         }
796
797         return;
798
799 error:
800         g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
801 }
802
803 static void add_handler(GAtServer *server)
804 {
805         g_at_server_set_debug(server, server_debug, "Server");
806
807         g_at_server_register(server, "+CGMI",    cgmi_cb,    NULL, NULL);
808         g_at_server_register(server, "+CGMM",    cgmm_cb,    NULL, NULL);
809         g_at_server_register(server, "+CGMR",    cgmr_cb,    NULL, NULL);
810         g_at_server_register(server, "+CGSN",    cgsn_cb,    NULL, NULL);
811         g_at_server_register(server, "+CFUN",    cfun_cb,    NULL, NULL);
812         g_at_server_register(server, "+CPIN",    cpin_cb,    NULL, NULL);
813         g_at_server_register(server, "+COPS",    cops_cb,    NULL, NULL);
814         g_at_server_register(server, "+CREG",    creg_cb,    NULL, NULL);
815         g_at_server_register(server, "+CGREG",   cgreg_cb,   NULL, NULL);
816         g_at_server_register(server, "+CGATT",   cgatt_cb,   NULL, NULL);
817         g_at_server_register(server, "+CGDATA",  cgdata_cb,  NULL, NULL);
818         g_at_server_register(server, "+CGDCONT", cgdcont_cb, NULL, NULL);
819         g_at_server_register(server, "+CIMI",    cimi_cb,    NULL, NULL);
820         g_at_server_register(server, "+CSMS",    csms_cb,    NULL, NULL);
821         g_at_server_register(server, "+CMGF",    cmgf_cb,    NULL, NULL);
822         g_at_server_register(server, "+CPMS",    cpms_cb,    NULL, NULL);
823         g_at_server_register(server, "+CNMI",    cnmi_cb,    NULL, NULL);
824         g_at_server_register(server, "+CSCS",    cscs_cb,    NULL, NULL);
825         g_at_server_register(server, "+CMGL",    cmgl_cb,    NULL, NULL);
826         g_at_server_register(server, "+CPBS",    cpbs_cb,    NULL, NULL);
827         g_at_server_register(server, "D",        dial_cb,    NULL, NULL);
828 }
829
830 static void server_destroy(gpointer user)
831 {
832         struct sock_server *data = user;
833
834         g_free(data);
835 }
836
837 static void set_raw_mode(int fd)
838 {
839         struct termios ti;
840
841         memset(&ti, 0, sizeof(ti));
842         tcgetattr(fd, &ti);
843         tcflush(fd, TCIOFLUSH);
844         cfmakeraw(&ti);
845         tcsetattr(fd, TCSANOW, &ti);
846 }
847
848 static gboolean create_tty(const char *modem_path)
849 {
850         int master, slave;
851         char pty_name[256];
852         GIOChannel *server_io;
853
854         if (modem_path == NULL)
855                 return FALSE;
856
857         if (openpty(&master, &slave, pty_name, NULL, NULL) < 0)
858                 return FALSE;
859
860         set_raw_mode(slave);
861
862         g_print("new pty is created at %s\n", pty_name);
863
864         server_io = g_io_channel_unix_new(master);
865
866         main_server = g_at_server_new(server_io);
867         if (main_server == NULL) {
868                 g_io_channel_shutdown(server_io, FALSE, NULL);
869                 g_io_channel_unref(server_io);
870
871                 return FALSE;
872         }
873
874         g_io_channel_unref(server_io);
875
876         return TRUE;
877 }
878
879 static gboolean on_socket_connected(GIOChannel *chan, GIOCondition cond,
880                                                         gpointer user)
881 {
882         struct sockaddr saddr;
883         unsigned int len = sizeof(saddr);
884         int fd;
885         GIOChannel *client_io = NULL;
886         struct sock_server *data = user;
887
888         if (cond != G_IO_IN)
889                 goto error;
890
891         fd = accept(data->server_sock, &saddr, &len);
892         if (fd == -1)
893                 goto error;
894
895         client_io = g_io_channel_unix_new(fd);
896
897         main_server = g_at_server_new(client_io);
898         g_io_channel_unref(client_io);
899
900         if (main_server == NULL)
901                 goto error;
902
903         add_handler(main_server);
904
905         return TRUE;
906
907 error:
908         g_free(data);
909
910         return FALSE;
911 }
912
913 static struct sock_server *socket_common(int sk, struct sockaddr *addr,
914                                                 const char *modem_path)
915 {
916         struct sock_server *sock;
917         int reuseaddr = 1;
918
919         setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
920
921         if (bind(sk, addr, sizeof(struct sockaddr)) < 0) {
922                 g_print("Can't bind socket: %s (%d)", strerror(errno), errno);
923
924                 close(sk);
925
926                 return NULL;
927         }
928
929         if (listen(sk, 1) < 0) {
930                 g_print("Can't listen on socket: %s (%d)",
931                                                 strerror(errno), errno);
932
933                 close(sk);
934
935                 return NULL;
936         }
937
938         sock = g_try_new0(struct sock_server, 1);
939         if (sock == NULL)
940                 return FALSE;
941
942         sock->server_sock = sk;
943
944         return sock;
945 }
946
947 static gboolean create_tcp(const char *modem_path, int port)
948 {
949         struct sockaddr_in addr;
950         int sk;
951         struct sock_server *server;
952         GIOChannel *server_io;
953
954         if (modem_path == NULL)
955                 return FALSE;
956
957         sk = socket(PF_INET, SOCK_STREAM, 0);
958         if (sk < 0) {
959                 g_print("Can't create tcp/ip socket: %s (%d)\n",
960                                                 strerror(errno), errno);
961                 return FALSE;
962         }
963
964         memset(&addr, 0, sizeof(addr));
965
966         addr.sin_family = AF_INET;
967         addr.sin_addr.s_addr = INADDR_ANY;
968         addr.sin_port = htons(port);
969
970         server = socket_common(sk, (struct sockaddr *) &addr, modem_path);
971         if (server == NULL)
972                 return FALSE;
973
974         g_print("new tcp is created at tcp port %d\n", port);
975
976         server_io = g_io_channel_unix_new(sk);
977
978         g_io_channel_set_close_on_unref(server_io, TRUE);
979
980         server_watch = g_io_add_watch_full(server_io,
981                                 G_PRIORITY_DEFAULT,
982                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
983                                 on_socket_connected, server, server_destroy);
984
985         g_io_channel_unref(server_io);
986
987         return TRUE;
988 }
989
990 static gboolean create_unix(const char *modem_path, const char *sock_path)
991 {
992         struct sockaddr_un addr;
993         int sk;
994         struct sock_server *server;
995         GIOChannel *server_io;
996
997         if (modem_path == NULL)
998                 return FALSE;
999
1000         sk = socket(AF_UNIX, SOCK_STREAM, 0);
1001         if (sk < 0) {
1002                 g_print("Can't create unix socket: %s (%d)\n",
1003                                                 strerror(errno), errno);
1004
1005                 return FALSE;
1006         }
1007
1008         memset(&addr, 0, sizeof(addr));
1009
1010         addr.sun_family = AF_UNIX;
1011         strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);
1012
1013         /* Unlink any existing socket for this session */
1014         unlink(addr.sun_path);
1015
1016         server = socket_common(sk, (struct sockaddr *) &addr, modem_path);
1017         if (server == NULL)
1018                 return FALSE;
1019
1020         g_print("new unix socket is created at %s\n", sock_path);
1021
1022         server_io = g_io_channel_unix_new(sk);
1023
1024         g_io_channel_set_close_on_unref(server_io, TRUE);
1025
1026         server_watch = g_io_add_watch_full(server_io,
1027                                 G_PRIORITY_DEFAULT,
1028                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
1029                                 on_socket_connected, server, server_destroy);
1030
1031         g_io_channel_unref(server_io);
1032
1033         return TRUE;
1034 }
1035
1036 static void test_server(int type)
1037 {
1038         switch (type) {
1039         case 0:
1040                 if (create_tty("/phonesim1") == FALSE)
1041                         exit(1);
1042
1043                 add_handler(main_server);
1044                 break;
1045         case 1:
1046                 if (create_tcp("/phonesim1", DEFAULT_TCP_PORT) == FALSE)
1047                         exit(1);
1048                 break;
1049         case 2:
1050                 if (create_unix("/phonesim1", DEFAULT_SOCK_PATH) == FALSE)
1051                         exit(1);
1052                 break;
1053         }
1054 }
1055
1056 static gboolean signal_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
1057 {
1058         int signal_fd = GPOINTER_TO_INT(data);
1059         struct signalfd_siginfo si;
1060         ssize_t res;
1061
1062         if (cond & (G_IO_NVAL | G_IO_ERR))
1063                 return FALSE;
1064
1065         res = read(signal_fd, &si, sizeof(si));
1066         if (res != sizeof(si))
1067                 return FALSE;
1068
1069         switch (si.ssi_signo) {
1070         case SIGINT:
1071                 server_cleanup();
1072                 break;
1073         case SIGTERM:
1074                 server_cleanup();
1075                 break;
1076         default:
1077                 break;
1078         }
1079
1080         return TRUE;
1081 }
1082
1083 static int create_signal_io(void)
1084 {
1085         sigset_t mask;
1086         GIOChannel *signal_io;
1087         int signal_fd, signal_source;
1088
1089         sigemptyset(&mask);
1090         sigaddset(&mask, SIGTERM);
1091         sigaddset(&mask, SIGINT);
1092
1093         if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
1094                 g_error("Can't set signal mask");
1095                 return 1;
1096         }
1097
1098         signal_fd = signalfd(-1, &mask, 0);
1099         if (signal_fd < 0) {
1100                 g_error("Can't create signal filedescriptor");
1101                 return 1;
1102         }
1103
1104         signal_io = g_io_channel_unix_new(signal_fd);
1105
1106         g_io_channel_set_close_on_unref(signal_io, TRUE);
1107
1108         signal_source = g_io_add_watch(signal_io,
1109                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
1110                         signal_cb, GINT_TO_POINTER(signal_fd));
1111
1112         g_io_channel_unref(signal_io);
1113
1114         return signal_source;
1115 }
1116
1117 static void usage(void)
1118 {
1119         g_print("test-server - AT Server testing\n"
1120                 "Usage:\n");
1121         g_print("\ttest-server [-t type]\n");
1122         g_print("Types:\n"
1123                 "\t0: Pseudo TTY port (default)\n"
1124                 "\t1: TCP sock at port 12346)\n"
1125                 "\t2: Unix sock at ./server_sock\n");
1126 }
1127
1128 int main(int argc, char **argv)
1129 {
1130         int opt, signal_source;
1131         int type = 0;
1132
1133         while ((opt = getopt(argc, argv, "ht:")) != EOF) {
1134                 switch (opt) {
1135                 case 't':
1136                         type = atoi(optarg);
1137                         break;
1138                 case 'h':
1139                         usage();
1140                         exit(1);
1141                         break;
1142                 default:
1143                         break;
1144                 }
1145         }
1146
1147         test_server(type);
1148
1149         signal_source = create_signal_io();
1150
1151         mainloop = g_main_loop_new(NULL, FALSE);
1152
1153         g_main_loop_run(mainloop);
1154
1155         g_main_loop_unref(mainloop);
1156
1157         g_source_remove(signal_source);
1158
1159         return 0;
1160 }