1 /* $Id$ */
2 /*
3  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "pjsua_app.h"
21 
22 #define THIS_FILE	"main.c"
23 
24 static pj_bool_t	    running = PJ_TRUE;
25 static pj_status_t	    receive_end_sig;
26 static pj_thread_t	    *sig_thread;
27 static pjsua_app_cfg_t	    cfg;
28 
29 /* Called when CLI (re)started */
on_app_started(pj_status_t status,const char * msg)30 void on_app_started(pj_status_t status, const char *msg)
31 {
32     pj_perror(3, THIS_FILE, status, (msg)?msg:"");
33 }
34 
on_app_stopped(pj_bool_t restart,int argc,char ** argv)35 void on_app_stopped(pj_bool_t restart, int argc, char** argv)
36 {
37     if (argv) {
38 	cfg.argc = argc;
39 	cfg.argv = argv;
40     }
41 
42     running = restart;
43 }
44 
45 #if defined(PJ_WIN32) && PJ_WIN32!=0
46 #include <windows.h>
47 
48 static pj_thread_desc handler_desc;
49 
CtrlHandler(DWORD fdwCtrlType)50 static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
51 {
52     switch (fdwCtrlType)
53     {
54         // Handle the CTRL+C signal.
55 
56         case CTRL_C_EVENT:
57         case CTRL_CLOSE_EVENT:
58         case CTRL_BREAK_EVENT:
59         case CTRL_LOGOFF_EVENT:
60         case CTRL_SHUTDOWN_EVENT:
61 	    pj_thread_register("ctrlhandler", handler_desc, &sig_thread);
62 	    PJ_LOG(3,(THIS_FILE, "Ctrl-C detected, quitting.."));
63 	    receive_end_sig = PJ_TRUE;
64             pjsua_app_destroy();
65 	    ExitProcess(1);
66             PJ_UNREACHED(return TRUE;)
67 
68         default:
69 
70             return FALSE;
71     }
72 }
73 
setup_socket_signal()74 static void setup_socket_signal()
75 {
76 }
77 
setup_signal_handler(void)78 static void setup_signal_handler(void)
79 {
80     SetConsoleCtrlHandler(&CtrlHandler, TRUE);
81 }
82 
83 #elif PJ_LINUX || PJ_DARWINOS
84 
85 #include <execinfo.h>
86 #include <signal.h>
87 #include <stdio.h>
88 #include <stdlib.h>
89 #include <unistd.h>
print_stack(int sig)90 static void print_stack(int sig)
91 {
92     void *array[16];
93     size_t size;
94 
95     size = backtrace(array, 16);
96     fprintf(stderr, "Error: signal %d:\n", sig);
97     backtrace_symbols_fd(array, size, STDERR_FILENO);
98     exit(1);
99 }
100 
setup_socket_signal()101 static void setup_socket_signal()
102 {
103     signal(SIGPIPE, SIG_IGN);
104 }
105 
setup_signal_handler(void)106 static void setup_signal_handler(void)
107 {
108     signal(SIGSEGV, &print_stack);
109     signal(SIGABRT, &print_stack);
110 }
111 
112 #else
113 
114 #include <signal.h>
115 
setup_socket_signal()116 static void setup_socket_signal()
117 {
118     signal(SIGPIPE, SIG_IGN);
119 }
120 
setup_signal_handler(void)121 static void setup_signal_handler(void) {}
122 
123 #endif
124 
main_func(int argc,char * argv[])125 int main_func(int argc, char *argv[])
126 {
127     pj_status_t status = PJ_TRUE;
128 
129     pj_bzero(&cfg, sizeof(cfg));
130     cfg.on_started = &on_app_started;
131     cfg.on_stopped = &on_app_stopped;
132     cfg.argc = argc;
133     cfg.argv = argv;
134 
135     setup_signal_handler();
136     setup_socket_signal();
137 
138     while (running) {
139 	status = pjsua_app_init(&cfg);
140 	if (status == PJ_SUCCESS) {
141 	    status = pjsua_app_run(PJ_TRUE);
142 	} else {
143 	    running = PJ_FALSE;
144 	}
145 
146 	if (!receive_end_sig) {
147 	    pjsua_app_destroy();
148 
149 	    /* This is on purpose */
150 	    pjsua_app_destroy();
151 	} else {
152 	    pj_thread_join(sig_thread);
153 	}
154     }
155     return 0;
156 }
157 
main(int argc,char * argv[])158 int main(int argc, char *argv[])
159 {
160     return pj_run_app(&main_func, argc, argv, 0);
161 }
162