3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
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.
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.
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
32 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
37 #include <sys/signalfd.h>
44 #include <sys/types.h>
47 #include "gatserver.h"
49 #include "ringbuffer.h"
51 #define DEFAULT_TCP_PORT 12346
52 #define DEFAULT_SOCK_PATH "./server_sock"
53 #define IFCONFIG_PATH "/sbin/ifconfig"
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;
66 static GMainLoop *mainloop;
67 static GAtServer *main_server;
69 unsigned int server_watch;
71 static gboolean server_cleanup(void)
74 g_source_remove(server_watch);
81 g_at_server_unref(main_server);
84 unlink(DEFAULT_SOCK_PATH);
86 g_main_loop_quit(mainloop);
91 static void server_debug(const char *str, void *data)
93 g_print("%s: %s\n", (char *) data, str);
96 static gboolean execute(const char *cmd)
100 status = system(cmd);
102 g_print("Failed to execute command: %s\n", strerror(errno));
109 static void ppp_connect(const char *iface, const char *local, const char *peer,
110 const char *dns1, const char *dns2,
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);
121 snprintf(buf, sizeof(buf), "%s %s up", IFCONFIG_PATH, iface);
124 snprintf(buf, sizeof(buf), "%s %s %s pointopoint %s", IFCONFIG_PATH,
128 snprintf(buf, sizeof(buf), "echo 1 > /proc/sys/net/ipv4/ip_forward");
132 static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user)
134 GAtServer *server = user;
136 g_print("PPP Link down: %d\n", reason);
141 if (reason == G_AT_PPP_REASON_LINK_DEAD) {
142 g_at_server_unref(server);
147 g_at_server_resume(server);
148 g_at_server_set_debug(server, server_debug, "Server");
150 g_at_server_send_final(server, G_AT_SERVER_RESULT_NO_CARRIER);
154 static void open_ppp(gpointer user)
156 GAtIO *io = g_at_server_get_io(main_server);
158 g_at_server_suspend(main_server);
159 g_at_ppp_listen(ppp, io);
162 static gboolean setup_ppp(GAtServer *server)
165 ppp = g_at_ppp_server_new("192.168.1.1");
169 g_at_ppp_set_debug(ppp, server_debug, "PPP");
171 g_at_ppp_set_credentials(ppp, "", "");
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");
182 static void cgmi_cb(GAtServer *server, GAtServerRequestType type,
183 GAtResult *cmd, gpointer user)
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);
190 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
191 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
194 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
198 static void cgmm_cb(GAtServer *server, GAtServerRequestType type,
199 GAtResult *cmd, gpointer user)
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);
206 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
207 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
210 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
214 static void cgmr_cb(GAtServer *server, GAtServerRequestType type,
215 GAtResult *cmd, gpointer user)
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);
225 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
226 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
229 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
233 static void cgsn_cb(GAtServer *server, GAtServerRequestType type,
234 GAtResult *cmd, gpointer user)
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);
241 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
242 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
245 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
249 static gboolean send_ok(gpointer user)
251 GAtServer *server = user;
253 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
258 static void cfun_cb(GAtServer *server, GAtServerRequestType type,
259 GAtResult *cmd, gpointer user)
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);
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);
273 case G_AT_SERVER_REQUEST_TYPE_SET:
278 g_at_result_iter_init(&iter, cmd);
279 g_at_result_iter_next(&iter, "");
281 if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
284 if (mode != 0 && mode != 1)
287 if (modem_mode == mode) {
288 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
293 g_timeout_add_seconds(1, send_ok, server);
303 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
306 static void cpin_cb(GAtServer *server, GAtServerRequestType type,
307 GAtResult *cmd, gpointer user)
309 if (modem_mode == 0) {
310 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
315 case G_AT_SERVER_REQUEST_TYPE_SET:
316 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
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);
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);
327 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
332 static gboolean do_netreg(gpointer user)
334 GAtServer *server = user;
342 switch (modem_creg) {
345 snprintf(buf, sizeof(buf), "+CREG: %d", network_status);
346 g_at_server_send_unsolicited(server, buf);
353 static void cops_cb(GAtServer *server, GAtServerRequestType type,
354 GAtResult *cmd, gpointer user)
356 if (modem_mode == 0) {
357 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
362 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
363 g_timeout_add_seconds(3, send_ok, server);
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);
369 case G_AT_SERVER_REQUEST_TYPE_SET:
371 GAtServerResult result;
375 g_at_result_iter_init(&iter, cmd);
376 g_at_result_iter_next(&iter, "");
378 if (g_at_result_iter_next_number(&iter, &mode) == TRUE) {
380 g_timeout_add_seconds(2, do_netreg, server);
381 result = G_AT_SERVER_RESULT_OK;
383 result = G_AT_SERVER_RESULT_ERROR;
385 result = G_AT_SERVER_RESULT_ERROR;
387 g_at_server_send_final(server, result);
391 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
396 static void creg_cb(GAtServer *server, GAtServerRequestType type,
397 GAtResult *cmd, gpointer user)
401 if (modem_mode == 0) {
402 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
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);
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);
417 case G_AT_SERVER_REQUEST_TYPE_SET:
422 g_at_result_iter_init(&iter, cmd);
423 g_at_result_iter_next(&iter, "");
425 if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
428 if (mode != 0 && mode != 1 && mode != 2)
432 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
442 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
445 static void cgreg_cb(GAtServer *server, GAtServerRequestType type,
446 GAtResult *cmd, gpointer user)
450 if (modem_mode == 0) {
451 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
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);
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);
466 case G_AT_SERVER_REQUEST_TYPE_SET:
471 g_at_result_iter_init(&iter, cmd);
472 g_at_result_iter_next(&iter, "");
474 if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
477 if (mode != 0 && mode != 1 && mode != 2)
481 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
491 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
494 static void cgatt_cb(GAtServer *server, GAtServerRequestType type,
495 GAtResult *cmd, gpointer user)
499 if (modem_mode == 0) {
500 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
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);
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);
514 case G_AT_SERVER_REQUEST_TYPE_SET:
519 g_at_result_iter_init(&iter, cmd);
520 g_at_result_iter_next(&iter, "");
522 if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
525 if (mode != 0 && mode != 1)
528 if (network_attach == mode) {
529 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
533 network_attach = mode;
534 g_timeout_add_seconds(1, send_ok, server);
544 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
547 static void cgdata_cb(GAtServer *server, GAtServerRequestType type,
548 GAtResult *cmd, gpointer user)
552 if (modem_mode == 0) {
553 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
558 case G_AT_SERVER_REQUEST_TYPE_SET:
559 if (setup_ppp(server) == FALSE)
562 g_at_server_send_intermediate(server, "CONNECT");
565 io = g_at_server_get_io(server);
566 g_at_io_set_write_done(io, open_ppp, server);
570 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
575 static void cgdcont_cb(GAtServer *server, GAtServerRequestType type,
576 GAtResult *cmd, gpointer user)
578 if (modem_mode == 0) {
579 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
584 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
585 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
587 case G_AT_SERVER_REQUEST_TYPE_QUERY:
588 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
590 case G_AT_SERVER_REQUEST_TYPE_SET:
591 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
594 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
599 static void cimi_cb(GAtServer *server, GAtServerRequestType type,
600 GAtResult *cmd, gpointer user)
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);
607 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
608 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
611 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
616 static void csms_cb(GAtServer *server, GAtServerRequestType type,
617 GAtResult *cmd, gpointer user)
620 case G_AT_SERVER_REQUEST_TYPE_SET:
621 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
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);
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);
632 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
637 static void cmgf_cb(GAtServer *server, GAtServerRequestType type,
638 GAtResult *cmd, gpointer user)
641 case G_AT_SERVER_REQUEST_TYPE_SET:
642 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
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);
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);
653 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
658 static void cpms_cb(GAtServer *server, GAtServerRequestType type,
659 GAtResult *cmd, gpointer user)
664 case G_AT_SERVER_REQUEST_TYPE_SET:
665 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
667 case G_AT_SERVER_REQUEST_TYPE_QUERY:
668 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
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);
676 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
681 static void cnmi_cb(GAtServer *server, GAtServerRequestType type,
682 GAtResult *cmd, gpointer user)
687 case G_AT_SERVER_REQUEST_TYPE_SET:
688 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
690 case G_AT_SERVER_REQUEST_TYPE_QUERY:
691 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
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);
699 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
704 static void cscs_cb(GAtServer *server, GAtServerRequestType type,
705 GAtResult *cmd, gpointer user)
710 case G_AT_SERVER_REQUEST_TYPE_SET:
711 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
713 case G_AT_SERVER_REQUEST_TYPE_QUERY:
714 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
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);
722 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
727 static void cmgl_cb(GAtServer *server, GAtServerRequestType type,
728 GAtResult *cmd, gpointer user)
731 case G_AT_SERVER_REQUEST_TYPE_SET:
732 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
734 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
735 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
738 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
743 static void cpbs_cb(GAtServer *server, GAtServerRequestType type,
744 GAtResult *cmd, gpointer user)
749 case G_AT_SERVER_REQUEST_TYPE_SET:
750 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
752 case G_AT_SERVER_REQUEST_TYPE_QUERY:
753 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
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);
761 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
766 static void dial_cb(GAtServer *server, GAtServerRequestType type,
767 GAtResult *cmd, gpointer user)
770 const char *dial_str;
773 if (type != G_AT_SERVER_REQUEST_TYPE_SET)
776 g_at_result_iter_init(&iter, cmd);
777 g_at_result_iter_next(&iter, "");
779 dial_str = g_at_result_iter_raw_line(&iter);
780 if (dial_str == NULL)
783 g_print("dial call %s\n", dial_str);
786 if (c == '*' || c == '#' || c == 'T' || c == 't') {
787 GAtIO *io = g_at_server_get_io(server);
789 if (setup_ppp(server) == FALSE)
792 g_at_server_send_intermediate(server, "CONNECT");
794 g_at_io_set_write_done(io, open_ppp, server);
800 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
803 static void add_handler(GAtServer *server)
805 g_at_server_set_debug(server, server_debug, "Server");
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);
830 static void server_destroy(gpointer user)
832 struct sock_server *data = user;
837 static void set_raw_mode(int fd)
841 memset(&ti, 0, sizeof(ti));
843 tcflush(fd, TCIOFLUSH);
845 tcsetattr(fd, TCSANOW, &ti);
848 static gboolean create_tty(const char *modem_path)
852 GIOChannel *server_io;
854 if (modem_path == NULL)
857 if (openpty(&master, &slave, pty_name, NULL, NULL) < 0)
862 g_print("new pty is created at %s\n", pty_name);
864 server_io = g_io_channel_unix_new(master);
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);
874 g_io_channel_unref(server_io);
879 static gboolean on_socket_connected(GIOChannel *chan, GIOCondition cond,
882 struct sockaddr saddr;
883 unsigned int len = sizeof(saddr);
885 GIOChannel *client_io = NULL;
886 struct sock_server *data = user;
891 fd = accept(data->server_sock, &saddr, &len);
895 client_io = g_io_channel_unix_new(fd);
897 main_server = g_at_server_new(client_io);
898 g_io_channel_unref(client_io);
900 if (main_server == NULL)
903 add_handler(main_server);
913 static struct sock_server *socket_common(int sk, struct sockaddr *addr,
914 const char *modem_path)
916 struct sock_server *sock;
919 setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
921 if (bind(sk, addr, sizeof(struct sockaddr)) < 0) {
922 g_print("Can't bind socket: %s (%d)", strerror(errno), errno);
929 if (listen(sk, 1) < 0) {
930 g_print("Can't listen on socket: %s (%d)",
931 strerror(errno), errno);
938 sock = g_try_new0(struct sock_server, 1);
942 sock->server_sock = sk;
947 static gboolean create_tcp(const char *modem_path, int port)
949 struct sockaddr_in addr;
951 struct sock_server *server;
952 GIOChannel *server_io;
954 if (modem_path == NULL)
957 sk = socket(PF_INET, SOCK_STREAM, 0);
959 g_print("Can't create tcp/ip socket: %s (%d)\n",
960 strerror(errno), errno);
964 memset(&addr, 0, sizeof(addr));
966 addr.sin_family = AF_INET;
967 addr.sin_addr.s_addr = INADDR_ANY;
968 addr.sin_port = htons(port);
970 server = socket_common(sk, (struct sockaddr *) &addr, modem_path);
974 g_print("new tcp is created at tcp port %d\n", port);
976 server_io = g_io_channel_unix_new(sk);
978 g_io_channel_set_close_on_unref(server_io, TRUE);
980 server_watch = g_io_add_watch_full(server_io,
982 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
983 on_socket_connected, server, server_destroy);
985 g_io_channel_unref(server_io);
990 static gboolean create_unix(const char *modem_path, const char *sock_path)
992 struct sockaddr_un addr;
994 struct sock_server *server;
995 GIOChannel *server_io;
997 if (modem_path == NULL)
1000 sk = socket(AF_UNIX, SOCK_STREAM, 0);
1002 g_print("Can't create unix socket: %s (%d)\n",
1003 strerror(errno), errno);
1008 memset(&addr, 0, sizeof(addr));
1010 addr.sun_family = AF_UNIX;
1011 strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);
1013 /* Unlink any existing socket for this session */
1014 unlink(addr.sun_path);
1016 server = socket_common(sk, (struct sockaddr *) &addr, modem_path);
1020 g_print("new unix socket is created at %s\n", sock_path);
1022 server_io = g_io_channel_unix_new(sk);
1024 g_io_channel_set_close_on_unref(server_io, TRUE);
1026 server_watch = g_io_add_watch_full(server_io,
1028 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
1029 on_socket_connected, server, server_destroy);
1031 g_io_channel_unref(server_io);
1036 static void test_server(int type)
1040 if (create_tty("/phonesim1") == FALSE)
1043 add_handler(main_server);
1046 if (create_tcp("/phonesim1", DEFAULT_TCP_PORT) == FALSE)
1050 if (create_unix("/phonesim1", DEFAULT_SOCK_PATH) == FALSE)
1056 static gboolean signal_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
1058 int signal_fd = GPOINTER_TO_INT(data);
1059 struct signalfd_siginfo si;
1062 if (cond & (G_IO_NVAL | G_IO_ERR))
1065 res = read(signal_fd, &si, sizeof(si));
1066 if (res != sizeof(si))
1069 switch (si.ssi_signo) {
1083 static int create_signal_io(void)
1086 GIOChannel *signal_io;
1087 int signal_fd, signal_source;
1090 sigaddset(&mask, SIGTERM);
1091 sigaddset(&mask, SIGINT);
1093 if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
1094 g_error("Can't set signal mask");
1098 signal_fd = signalfd(-1, &mask, 0);
1099 if (signal_fd < 0) {
1100 g_error("Can't create signal filedescriptor");
1104 signal_io = g_io_channel_unix_new(signal_fd);
1106 g_io_channel_set_close_on_unref(signal_io, TRUE);
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));
1112 g_io_channel_unref(signal_io);
1114 return signal_source;
1117 static void usage(void)
1119 g_print("test-server - AT Server testing\n"
1121 g_print("\ttest-server [-t type]\n");
1123 "\t0: Pseudo TTY port (default)\n"
1124 "\t1: TCP sock at port 12346)\n"
1125 "\t2: Unix sock at ./server_sock\n");
1128 int main(int argc, char **argv)
1130 int opt, signal_source;
1133 while ((opt = getopt(argc, argv, "ht:")) != EOF) {
1136 type = atoi(optarg);
1149 signal_source = create_signal_io();
1151 mainloop = g_main_loop_new(NULL, FALSE);
1153 g_main_loop_run(mainloop);
1155 g_main_loop_unref(mainloop);
1157 g_source_remove(signal_source);