From 27155bcb71396d65a7a22eb2079344ede30d0077 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 10 Jul 2012 12:05:26 -0500 Subject: [PATCH 01/16] come to ClueCon its in one month --- libs/esl/fs_cli.c | 11 +++++++---- libs/esl/src/include/cc.h | 3 +++ 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 libs/esl/src/include/cc.h diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 408c946d29..8532e23391 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -916,15 +916,18 @@ static const char *banner = "* Paypal Donations Appreciated: paypal@freeswitch.org *\n" "* Brought to you by ClueCon http://www.cluecon.com/ *\n" "*******************************************************\n" - "\n" - "Type /help to see a list of commands\n\n\n"; + "\n"; + +static const char *inf = "Type /help to see a list of commands\n\n\n"; static void print_banner(FILE *stream) { +#include + #ifndef WIN32 - fprintf(stream, "%s%s", output_text_color, banner); + fprintf(stream, "%s%s%s\n%s", output_text_color, banner, cc, inf); #else - fprintf(stream, "%s", banner); + fprintf(stream, "%s%s\n%s", banner, cc, inf); #endif } diff --git a/libs/esl/src/include/cc.h b/libs/esl/src/include/cc.h new file mode 100644 index 0000000000..573a7f7332 --- /dev/null +++ b/libs/esl/src/include/cc.h @@ -0,0 +1,3 @@ + +const char *cc = "\n.========================================================================================================.\n| ____ _____ ____ _ ____ _ _ ____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ \\ |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | __) | |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |/ __/ |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|_____| |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | _ | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___/ ( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ _____ _ _ ___ _ _ ____ ___ _ ____ |\n| / \\ _ _ __ _ _ _ ___| |_ |___ | |_| |__ / _ \\| |_| |__ |___ \\ / _ \\/ |___ \\ |\n| / _ \\| | | |/ _` | | | / __| __| / /| __| '_ \\ _____ | (_) | __| '_ \\ __) | | | | | __) | |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ / / | |_| | | | |_____| \\__, | |_| | | | / __/| |_| | |/ __/ |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| /_/ \\__|_| |_| /_/ \\__|_| |_| |_____|\\___/|_|_____| |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n\n"; + From 6904ae6f3be9d973f066fa9078061d9a955d885c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 10 Jul 2012 13:28:38 -0500 Subject: [PATCH 02/16] FS-4404 regression from b9b4db7d40159ec1b8d2a0c0f41655339daa0887 --- src/mod/endpoints/mod_sofia/sofia.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index e5722566e6..9364b50569 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1074,13 +1074,15 @@ static void our_sofia_event_callback(nua_event_t event, case nua_i_cancel: - switch_channel_set_variable(channel, "sip_hangup_disposition", "recv_cancel"); + if (sip && channel) { + switch_channel_set_variable(channel, "sip_hangup_disposition", "recv_cancel"); - if (sip && channel && sip->sip_reason) { - char *reason_header = sip_header_as_string(nh->nh_home, (void *) sip->sip_reason); + if (sip->sip_reason) { + char *reason_header = sip_header_as_string(nh->nh_home, (void *) sip->sip_reason); - if (!zstr(reason_header)) { - switch_channel_set_variable_partner(channel, "sip_reason", reason_header); + if (!zstr(reason_header)) { + switch_channel_set_variable_partner(channel, "sip_reason", reason_header); + } } } From 6c406aa0d9032512d45e1c7c84491e2afc784783 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 10 Jul 2012 13:32:35 -0500 Subject: [PATCH 03/16] add wait handler to forking code in ivrd --- libs/esl/ivrd.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libs/esl/ivrd.c b/libs/esl/ivrd.c index 2e2e6b2fa4..6098abcaf9 100644 --- a/libs/esl/ivrd.c +++ b/libs/esl/ivrd.c @@ -35,6 +35,15 @@ #include #include #include +#include + +static void handle_SIGCHLD(int sig) +{ + int status = 0; + + wait(&status); + return; +} static void my_forking_callback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in *addr) { @@ -43,6 +52,8 @@ static void my_forking_callback(esl_socket_t server_sock, esl_socket_t client_so const char *path; char arg[64] = { 0 }; + signal(SIGCHLD, handle_SIGCHLD); + if (fork()) { close(client_sock); return; From 293516be59f2495a0517f8297a337a2876786cc4 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 10 Jul 2012 22:44:11 -0500 Subject: [PATCH 04/16] FS-4370 --resolve --- src/switch_channel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/switch_channel.c b/src/switch_channel.c index 8c36f64fe7..99a4cc6121 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -3577,7 +3577,9 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables_check(switch_channel_t *c idx = atoi(ptr); } - if (vtype == 3 || (sub_val = (char *) switch_channel_get_variable_dup(channel, vname, SWITCH_TRUE, idx))) { + if (!sub_val) sub_val = vname; + + if ((sub_val = (char *) switch_channel_get_variable_dup(channel, vname, SWITCH_TRUE, idx))) { if (var_list && !switch_event_check_permission_list(var_list, vname)) { sub_val = "INVALID"; } From ba428a1559b2f689219ad3f41ffd9f20b2177c1e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 10 Jul 2012 23:04:16 -0500 Subject: [PATCH 05/16] FS-4406 please test asap and report back --- src/mod/endpoints/mod_sofia/sofia.c | 6 ++++-- src/mod/endpoints/mod_sofia/sofia_reg.c | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 9364b50569..b04cb89e37 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5041,11 +5041,13 @@ static void sofia_handle_sip_r_options(switch_core_session_t *session, int statu } else if (sofia_test_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL) && (status != 200 && status != 486) && sip && sip->sip_to) { char *sql; time_t now = switch_epoch_time_now(NULL); + const char *call_id = sip->sip_call_id->i_id; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Expire registration '%s@%s' due to options failure\n", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host); - sql = switch_mprintf("update sip_registrations set expires=%ld where sip_user='%s' and sip_host='%s'", - (long) now, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host); + sql = switch_mprintf("update sip_registrations set expires=%ld where sip_user='%s' and sip_host='%s' and call_id='%q'", + (long) now, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id); sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); } } diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 84367a23f3..1e17ad544e 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -551,15 +551,16 @@ int sofia_reg_nat_callback(void *pArg, int argc, char **argv, char **columnNames { sofia_profile_t *profile = (sofia_profile_t *) pArg; nua_handle_t *nh; - char to[128] = ""; + char to[512] = ""; sofia_destination_t *dst = NULL; switch_snprintf(to, sizeof(to), "sip:%s@%s", argv[1], argv[2]); + dst = sofia_glue_get_destination(argv[3]); switch_assert(dst); nh = nua_handle(profile->nua, NULL, SIPTAG_FROM_STR(profile->url), SIPTAG_TO_STR(to), NUTAG_URL(dst->contact), SIPTAG_CONTACT_STR(profile->url), - TAG_END()); + SIPTAG_CALL_ID_STR(argv[0]), TAG_END()); nua_handle_bind(nh, &mod_sofia_globals.destroy_private); nua_options(nh, NTATAG_SIP_T2(5000), From d6a395b6420108e9a4094ffa41c676ac46ba9f10 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Tue, 10 Jul 2012 14:47:38 +0200 Subject: [PATCH 06/16] freeswitch: Use switch_strlen_zero() to check for empty strings. Signed-off-by: Stefan Knoblich --- src/switch.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/switch.c b/src/switch.c index 30a6f1e7e1..d4a4e01694 100644 --- a/src/switch.c +++ b/src/switch.c @@ -437,7 +437,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-service")) { /* New installs will always have the service name specified, but keep a default for compat */ x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); } else { switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); @@ -450,7 +450,7 @@ int main(int argc, char *argv[]) char exePath[1024]; char servicePath[1024]; x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); } else { switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); @@ -485,7 +485,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-uninstall")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); } else { switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); @@ -521,7 +521,7 @@ int main(int argc, char *argv[]) #else if (local_argv[x] && !strcmp(local_argv[x], "-u")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { runas_user = local_argv[x]; } known_opt++; @@ -529,7 +529,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-g")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { runas_group = local_argv[x]; } known_opt++; @@ -641,7 +641,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-conf")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.conf_dir) { fprintf(stderr, "Allocation error\n"); @@ -658,7 +658,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-mod")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.mod_dir) { fprintf(stderr, "Allocation error\n"); @@ -674,7 +674,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-log")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.log_dir) { fprintf(stderr, "Allocation error\n"); @@ -692,7 +692,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-run")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.run_dir) { fprintf(stderr, "Allocation error\n"); @@ -709,7 +709,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-db")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.db_dir) { fprintf(stderr, "Allocation error\n"); @@ -726,7 +726,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-scripts")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.script_dir) { fprintf(stderr, "Allocation error\n"); @@ -742,7 +742,7 @@ int main(int argc, char *argv[]) if (local_argv[x] && !strcmp(local_argv[x], "-htdocs")) { x++; - if (local_argv[x] && strlen(local_argv[x])) { + if (!switch_strlen_zero(local_argv[x])) { SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.htdocs_dir) { fprintf(stderr, "Allocation error\n"); From 659ea9f117e189f89a5f29f44a69b90f995ae392 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Tue, 10 Jul 2012 15:08:59 +0200 Subject: [PATCH 07/16] freeswitch: Move usage description out of main() and improve cmdline option handling. Move empty cmdline option string check and "-help/-h/-?" handling to top of loop. Emit a proper error message for unknown options. (Just displaying the usage description, but not telling the user which option was wrong, is bad mojo). Signed-off-by: Stefan Knoblich --- src/switch.c | 98 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/src/switch.c b/src/switch.c index d4a4e01694..e5bcee3153 100644 --- a/src/switch.c +++ b/src/switch.c @@ -331,6 +331,50 @@ void daemonize(int do_wait) #endif +static const char const usage[] = + "Usage: freeswitch [OPTIONS]\n\n" + "These are the optional arguments you can pass to freeswitch:\n" +#ifdef WIN32 + "\t-service [name] -- start freeswitch as a service, cannot be used if loaded as a console app\n" + "\t-install [name] -- install freeswitch as a service, with optional service name\n" + "\t-uninstall -- remove freeswitch as a service\n" + "\t-monotonic-clock -- use monotonic clock as timer source\n" +#else + "\t-nf -- no forking\n" + "\t-u [user] -- specify user to switch to\n" + "\t-g [group] -- specify group to switch to\n" +#endif +#ifdef HAVE_SETRLIMIT + "\t-waste -- allow memory waste\n" + "\t-core -- dump cores\n" +#endif + "\t-help -- this message\n" + "\t-version -- print the version and exit\n" + "\t-rp -- enable high(realtime) priority settings\n" + "\t-lp -- enable low priority settings\n" + "\t-np -- enable normal priority settings (system defaults)\n" + "\t-vg -- run under valgrind\n" + "\t-nosql -- disable internal sql scoreboard\n" + "\t-heavy-timer -- Heavy Timer, possibly more accurate but at a cost\n" + "\t-nonat -- disable auto nat detection\n" + "\t-nonatmap -- disable auto nat port mapping\n" + "\t-nocal -- disable clock calibration\n" + "\t-nort -- disable clock clock_realtime\n" + "\t-stop -- stop freeswitch\n" + "\t-nc -- do not output to a console and background\n" +#ifndef WIN32 + "\t-ncwait -- do not output to a console and background but wait until the system is ready before exiting (implies -nc)\n" +#endif + "\t-c -- output to a console and stay in the foreground\n" + "\t-conf [confdir] -- specify an alternate config dir\n" + "\t-log [logdir] -- specify an alternate log dir\n" + "\t-run [rundir] -- specify an alternate run dir\n" + "\t-db [dbdir] -- specify an alternate db dir\n" + "\t-mod [moddir] -- specify an alternate mod dir\n" + "\t-htdocs [htdocsdir] -- specify an alternate htdocs dir\n" + "\t-scripts [scriptsdir] -- specify an alternate scripts dir\n"; + + /* the main application entry point */ int main(int argc, char *argv[]) { @@ -354,7 +398,6 @@ int main(int argc, char *argv[]) char *local_argv[1024] = { 0 }; int local_argc = argc; char *arg_argv[128] = { 0 }; - char *usageDesc; int alt_dirs = 0, log_set = 0, run_set = 0, do_kill = 0; int known_opt; int priority = 0; @@ -392,46 +435,16 @@ int main(int argc, char *argv[]) nc++; } - usageDesc = "these are the optional arguments you can pass to freeswitch\n" -#ifdef WIN32 - "\t-service [name] -- start freeswitch as a service, cannot be used if loaded as a console app\n" - "\t-install [name] -- install freeswitch as a service, with optional service name\n" - "\t-uninstall -- remove freeswitch as a service\n" - "\t-monotonic-clock -- use monotonic clock as timer source\n" -#else - "\t-nf -- no forking\n" - "\t-u [user] -- specify user to switch to\n" "\t-g [group] -- specify group to switch to\n" -#endif - "\t-help -- this message\n" "\t-version -- print the version and exit\n" -#ifdef HAVE_SETRLIMIT - "\t-waste -- allow memory waste\n" - "\t-core -- dump cores\n" -#endif - "\t-rp -- enable high(realtime) priority settings\n" - "\t-lp -- enable low priority settings\n" - "\t-np -- enable normal priority settings (system defaults)\n" - "\t-vg -- run under valgrind\n" - "\t-nosql -- disable internal sql scoreboard\n" - "\t-heavy-timer -- Heavy Timer, possibly more accurate but at a cost\n" - "\t-nonat -- disable auto nat detection\n" - "\t-nonatmap -- disable auto nat port mapping\n" - "\t-nocal -- disable clock calibration\n" - "\t-nort -- disable clock clock_realtime\n" - "\t-stop -- stop freeswitch\n" - "\t-nc -- do not output to a console and background\n" -#ifndef WIN32 - "\t-ncwait -- do not output to a console and background but wait until the system is ready before exiting (implies -nc)\n" -#endif - "\t-c -- output to a console and stay in the foreground\n" - "\t-conf [confdir] -- specify an alternate config dir\n" - "\t-log [logdir] -- specify an alternate log dir\n" - "\t-run [rundir] -- specify an alternate run dir\n" - "\t-db [dbdir] -- specify an alternate db dir\n" - "\t-mod [moddir] -- specify an alternate mod dir\n" - "\t-htdocs [htdocsdir] -- specify an alternate htdocs dir\n" "\t-scripts [scriptsdir] -- specify an alternate scripts dir\n"; - for (x = 1; x < local_argc; x++) { known_opt = 0; + + if (switch_strlen_zero(local_argv[x])) + continue; + + if (!strcmp(local_argv[x], "-help") || !strcmp(local_argv[x], "-h") || !strcmp(local_argv[x], "-?")) { + printf("%s\n", usage); + exit(EXIT_SUCCESS); + } #ifdef WIN32 if (x == 1) { if (local_argv[x] && !strcmp(local_argv[x], "-service")) { @@ -756,9 +769,10 @@ int main(int argc, char *argv[]) known_opt++; } - if (!known_opt || (local_argv[x] && (!strcmp(local_argv[x], "-help") || !strcmp(local_argv[x], "-h") || !strcmp(local_argv[x], "-?")))) { - printf("%s\n", usageDesc); - exit(0); + if (!known_opt) { + fprintf(stderr, "Unknown option '%s', see '%s -help' for a list of valid options\n", + local_argv[x], local_argv[0]); + exit(EXIT_FAILURE); } } From f9d0e249a11921175af0dc96cf9e524c1aa1d00f Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Tue, 10 Jul 2012 23:32:42 +0200 Subject: [PATCH 08/16] freeswitch: Rework option handling in main() and other clean ups. Use a chain of "else if" statements, drop known_opt completely. Added bonus: We stop trying to parse option arguments as (possible) options. Arguments of -u/-g and path options (-conf) now check whether their argument starts with a dash ('-') and error out in case it does (= next option, not a valid argument). Use PATH_MAX for everything that stores files / directories. Use switch_bool_t and SWITCH_TRUE/_FALSE for boolean variables. Use EXIT_SUCCESS/_FAILURE for exit() calls. Get rid of excessive indenting (especially in the win32 parts of main()). NOTE: Win32 parts untested. Signed-off-by: Stefan Knoblich --- src/switch.c | 468 +++++++++++++++++++++++++-------------------------- 1 file changed, 230 insertions(+), 238 deletions(-) diff --git a/src/switch.c b/src/switch.c index e5bcee3153..5edccd10b2 100644 --- a/src/switch.c +++ b/src/switch.c @@ -113,7 +113,7 @@ static void handle_SIGCHLD(int sig) static int freeswitch_kill_background() { FILE *f; /* FILE handle to open the pid file */ - char path[256] = ""; /* full path of the PID file */ + char path[PATH_MAX] = ""; /* full path of the PID file */ pid_t pid = 0; /* pid from the pid file */ /* set the globals so we can use the global paths. */ @@ -375,22 +375,34 @@ static const char const usage[] = "\t-scripts [scriptsdir] -- specify an alternate scripts dir\n"; +/** + * Check if value string starts with "-" + */ +static switch_bool_t is_option(const char *p) +{ + /* skip whitespaces */ + while ((*p == 13) || (*p == 10) || (*p == 9) || (*p == 32) || (*p == 11)) p++; + return (p[0] == '-'); +} + + /* the main application entry point */ int main(int argc, char *argv[]) { - char pid_path[256] = ""; /* full path to the pid file */ + char pid_path[PATH_MAX] = ""; /* full path to the pid file */ char pid_buffer[32] = ""; /* pid string */ char old_pid_buffer[32] = ""; /* pid string */ switch_size_t pid_len, old_pid_len; const char *err = NULL; /* error value for return from freeswitch initialization */ #ifndef WIN32 - int nf = 0; /* TRUE if we are running in nofork mode */ + switch_bool_t nf = SWITCH_FALSE; /* TRUE if we are running in nofork mode */ + switch_bool_t do_wait = SWITCH_FALSE; char *runas_user = NULL; char *runas_group = NULL; #else - int win32_service = 0; + switch_bool_t win32_service = SWITCH_FALSE; #endif - int nc = 0; /* TRUE if we are running in noconsole mode */ + switch_bool_t nc = SWITCH_FALSE; /* TRUE if we are running in noconsole mode */ pid_t pid = 0; int i, x; char *opts; @@ -399,11 +411,7 @@ int main(int argc, char *argv[]) int local_argc = argc; char *arg_argv[128] = { 0 }; int alt_dirs = 0, log_set = 0, run_set = 0, do_kill = 0; - int known_opt; int priority = 0; -#ifndef WIN32 - int do_wait = 0; -#endif #ifdef __sun switch_core_flag_t flags = SCF_USE_SQL; #else @@ -415,7 +423,7 @@ int main(int argc, char *argv[]) switch_memory_pool_t *pool = NULL; #ifdef HAVE_SETRLIMIT struct rlimit rlp; - int waste = 0; + switch_bool_t waste = SWITCH_FALSE; #endif for (x = 0; x < argc; x++) { @@ -430,13 +438,11 @@ int main(int argc, char *argv[]) } } - if (local_argv[0] && strstr(local_argv[0], "freeswitchd")) { - nc++; + nc = SWITCH_TRUE; } for (x = 1; x < local_argc; x++) { - known_opt = 0; if (switch_strlen_zero(local_argv[x])) continue; @@ -446,330 +452,317 @@ int main(int argc, char *argv[]) exit(EXIT_SUCCESS); } #ifdef WIN32 - if (x == 1) { - if (local_argv[x] && !strcmp(local_argv[x], "-service")) { - /* New installs will always have the service name specified, but keep a default for compat */ - x++; - if (!switch_strlen_zero(local_argv[x])) { - switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); - } else { - switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); - } - known_opt++; - win32_service++; - continue; - } - if (local_argv[x] && !strcmp(local_argv[x], "-install")) { - char exePath[1024]; - char servicePath[1024]; - x++; - if (!switch_strlen_zero(local_argv[x])) { - switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); - } else { - switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); - } - known_opt++; - GetModuleFileName(NULL, exePath, 1024); - snprintf(servicePath, sizeof(servicePath), "%s -service %s", exePath, service_name); - { /* Perform service installation */ - SC_HANDLE hService; - SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (!hSCManager) { - fprintf(stderr, "Could not open service manager (%d).\n", GetLastError()); - exit(1); - } - hService = CreateService(hSCManager, service_name, service_name, GENERIC_READ | GENERIC_EXECUTE | SERVICE_CHANGE_CONFIG, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, servicePath, NULL, NULL, NULL, NULL, /* Service start name */ - NULL); - if (!hService) { - fprintf(stderr, "Error creating freeswitch service (%d).\n", GetLastError()); - } else { - /* Set desc, and don't care if it succeeds */ - SERVICE_DESCRIPTION desc; - desc.lpDescription = "The FreeSWITCH service."; - if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &desc)) { - fprintf(stderr, "FreeSWITCH installed, but could not set the service description (%d).\n", GetLastError()); - } - CloseServiceHandle(hService); - } - CloseServiceHandle(hSCManager); - exit(0); - } + if (x == 1 && !strcmp(local_argv[x], "-service")) { + /* New installs will always have the service name specified, but keep a default for compat */ + x++; + if (!switch_strlen_zero(local_argv[x])) { + switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); + } else { + switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); } - if (local_argv[x] && !strcmp(local_argv[x], "-uninstall")) { - x++; - if (!switch_strlen_zero(local_argv[x])) { - switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); - } else { - switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); - } - { /* Do the uninstallation */ - SC_HANDLE hService; - SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (!hSCManager) { - fprintf(stderr, "Could not open service manager (%d).\n", GetLastError()); - exit(1); - } - hService = OpenService(hSCManager, service_name, DELETE); - known_opt++; - if (hService != NULL) { - /* remove the service! */ - if (!DeleteService(hService)) { - fprintf(stderr, "Error deleting service (%d).\n", GetLastError()); - } - CloseServiceHandle(hService); - } else { - fprintf(stderr, "Error opening service (%d).\n", GetLastError()); - } - CloseServiceHandle(hSCManager); - exit(0); - } - } + win32_service = SWITCH_TRUE; + continue; } - if (local_argv[x] && !strcmp(local_argv[x], "-monotonic-clock")) { + else if (x == 1 && !strcmp(local_argv[x], "-install")) { + char servicePath[PATH_MAX]; + char exePath[PATH_MAX]; + SC_HANDLE hService; + SC_HANDLE hSCManager; + SERVICE_DESCRIPTION desc; + desc.lpDescription = "The FreeSWITCH service."; + + x++; + if (!switch_strlen_zero(local_argv[x])) { + switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); + } else { + switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); + } + + GetModuleFileName(NULL, exePath, sizeof(exePath)); + snprintf(servicePath, sizeof(servicePath), "%s -service %s", exePath, service_name); + + /* Perform service installation */ + + hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (!hSCManager) { + fprintf(stderr, "Could not open service manager (%d).\n", GetLastError()); + exit(EXIT_FAILURE); + } + + hService = CreateService(hSCManager, service_name, service_name, GENERIC_READ | GENERIC_EXECUTE | SERVICE_CHANGE_CONFIG, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, + servicePath, NULL, NULL, NULL, NULL, /* Service start name */ NULL); + if (!hService) { + fprintf(stderr, "Error creating freeswitch service (%d).\n", GetLastError()); + CloseServiceHandle(hSCManager); + exit(EXIT_FAILURE); + } + + /* Set desc, and don't care if it succeeds */ + if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &desc)) { + fprintf(stderr, "FreeSWITCH installed, but could not set the service description (%d).\n", GetLastError()); + } + + CloseServiceHandle(hService); + CloseServiceHandle(hSCManager); + exit(EXIT_SUCCESS); + } + + else if (x == 1 && !strcmp(local_argv[x], "-uninstall")) { + SC_HANDLE hService; + SC_HANDLE hSCManager; + BOOL deleted; + + x++; + if (!switch_strlen_zero(local_argv[x])) { + switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); + } else { + switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); + } + + /* Do the uninstallation */ + hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (!hSCManager) { + fprintf(stderr, "Could not open service manager (%d).\n", GetLastError()); + exit(EXIT_FAILURE); + } + + hService = OpenService(hSCManager, service_name, DELETE); + if (!hService) { + fprintf(stderr, "Error opening service (%d).\n", GetLastError()); + CloseServiceHandle(hSCManager); + exit(EXIT_FAILURE); + } + + /* remove the service! */ + deleted = DeleteService(hService); + if (!deleted) { + fprintf(stderr, "Error deleting service (%d).\n", GetLastError()); + } + + CloseServiceHandle(hService); + CloseServiceHandle(hSCManager); + exit(deleted ? EXIT_SUCCESS : EXIT_FAILURE); + } + + else if (!strcmp(local_argv[x], "-monotonic-clock")) { flags |= SCF_USE_WIN32_MONOTONIC; - known_opt++; } #else - if (local_argv[x] && !strcmp(local_argv[x], "-u")) { + else if (!strcmp(local_argv[x], "-u")) { x++; - if (!switch_strlen_zero(local_argv[x])) { - runas_user = local_argv[x]; + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { + fprintf(stderr, "Option '%s' requires an argument!\n", local_argv[x - 1]); + exit(EXIT_FAILURE); } - known_opt++; + runas_user = local_argv[x]; } - if (local_argv[x] && !strcmp(local_argv[x], "-g")) { + else if (!strcmp(local_argv[x], "-g")) { x++; - if (!switch_strlen_zero(local_argv[x])) { - runas_group = local_argv[x]; + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { + fprintf(stderr, "Option '%s' requires an argument!\n", local_argv[x - 1]); + exit(EXIT_FAILURE); } - known_opt++; + runas_group = local_argv[x]; } - if (local_argv[x] && !strcmp(local_argv[x], "-nf")) { - nf++; - known_opt++; + else if (!strcmp(local_argv[x], "-nf")) { + nf = SWITCH_TRUE; } - if (local_argv[x] && !strcmp(local_argv[x], "-version")) { + else if (!strcmp(local_argv[x], "-version")) { fprintf(stdout, "FreeSWITCH version: %s\n", SWITCH_VERSION_FULL); - return 0; - known_opt++; + exit(EXIT_SUCCESS); } #endif #ifdef HAVE_SETRLIMIT - if (local_argv[x] && !strcmp(local_argv[x], "-core")) { + else if (!strcmp(local_argv[x], "-core")) { memset(&rlp, 0, sizeof(rlp)); rlp.rlim_cur = RLIM_INFINITY; rlp.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &rlp); - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-waste")) { + else if (!strcmp(local_argv[x], "-waste")) { fprintf(stderr, "WARNING: Wasting up to 8 megs of memory per thread.\n"); sleep(2); - waste++; - known_opt++; + waste = SWITCH_TRUE; } - if (local_argv[x] && !strcmp(local_argv[x], "-no-auto-stack")) { - waste++; - known_opt++; + else if (!strcmp(local_argv[x], "-no-auto-stack")) { + waste = SWITCH_TRUE; } #endif - - if (local_argv[x] && (!strcmp(local_argv[x], "-hp") || !strcmp(local_argv[x], "-rp"))) { + else if (!strcmp(local_argv[x], "-hp") || !strcmp(local_argv[x], "-rp")) { priority = 2; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-lp")) { + else if (!strcmp(local_argv[x], "-lp")) { priority = -1; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-np")) { + else if (!strcmp(local_argv[x], "-np")) { priority = 1; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-nosql")) { + else if (!strcmp(local_argv[x], "-nosql")) { flags &= ~SCF_USE_SQL; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-nonat")) { + else if (!strcmp(local_argv[x], "-nonat")) { flags &= ~SCF_USE_AUTO_NAT; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-nonatmap")) { + else if (!strcmp(local_argv[x], "-nonatmap")) { flags &= ~SCF_USE_NAT_MAPPING; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-heavy-timer")) { + else if (!strcmp(local_argv[x], "-heavy-timer")) { flags |= SCF_USE_HEAVY_TIMING; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-nort")) { + else if (!strcmp(local_argv[x], "-nort")) { flags &= ~SCF_USE_CLOCK_RT; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-nocal")) { + else if (!strcmp(local_argv[x], "-nocal")) { flags &= ~SCF_CALIBRATE_CLOCK; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-vg")) { + else if (!strcmp(local_argv[x], "-vg")) { flags |= SCF_VG; - known_opt++; } - if (local_argv[x] && !strcmp(local_argv[x], "-stop")) { - do_kill++; - known_opt++; + else if (!strcmp(local_argv[x], "-stop")) { + do_kill = SWITCH_TRUE; } - if (local_argv[x] && !strcmp(local_argv[x], "-nc")) { - nc++; - known_opt++; + else if (!strcmp(local_argv[x], "-nc")) { + nc = SWITCH_TRUE; } #ifndef WIN32 - if (local_argv[x] && !strcmp(local_argv[x], "-ncwait")) { - nc++; - do_wait++; - known_opt++; + else if (!strcmp(local_argv[x], "-ncwait")) { + nc = SWITCH_TRUE; + do_wait = SWITCH_TRUE; } #endif - if (local_argv[x] && !strcmp(local_argv[x], "-c")) { - nc = 0; - known_opt++; + else if (!strcmp(local_argv[x], "-c")) { + nc = SWITCH_FALSE; } - if (local_argv[x] && !strcmp(local_argv[x], "-conf")) { + else if (!strcmp(local_argv[x], "-conf")) { x++; - if (!switch_strlen_zero(local_argv[x])) { - SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(strlen(local_argv[x]) + 1); - if (!SWITCH_GLOBAL_dirs.conf_dir) { - fprintf(stderr, "Allocation error\n"); - return 255; - } - strcpy(SWITCH_GLOBAL_dirs.conf_dir, local_argv[x]); - alt_dirs++; - } else { + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -conf you must specify a config directory\n"); return 255; } - known_opt++; + + SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.conf_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.conf_dir, local_argv[x]); + alt_dirs++; } - if (local_argv[x] && !strcmp(local_argv[x], "-mod")) { + else if (!strcmp(local_argv[x], "-mod")) { x++; - if (!switch_strlen_zero(local_argv[x])) { - SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(strlen(local_argv[x]) + 1); - if (!SWITCH_GLOBAL_dirs.mod_dir) { - fprintf(stderr, "Allocation error\n"); - return 255; - } - strcpy(SWITCH_GLOBAL_dirs.mod_dir, local_argv[x]); - } else { + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -mod you must specify a module directory\n"); return 255; } - known_opt++; + + SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.mod_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.mod_dir, local_argv[x]); } - if (local_argv[x] && !strcmp(local_argv[x], "-log")) { + else if (!strcmp(local_argv[x], "-log")) { x++; - if (!switch_strlen_zero(local_argv[x])) { - SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(strlen(local_argv[x]) + 1); - if (!SWITCH_GLOBAL_dirs.log_dir) { - fprintf(stderr, "Allocation error\n"); - return 255; - } - strcpy(SWITCH_GLOBAL_dirs.log_dir, local_argv[x]); - alt_dirs++; - log_set++; - } else { + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -log you must specify a log directory\n"); return 255; } - known_opt++; + + SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.log_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.log_dir, local_argv[x]); + alt_dirs++; + log_set = SWITCH_TRUE; } - if (local_argv[x] && !strcmp(local_argv[x], "-run")) { + else if (!strcmp(local_argv[x], "-run")) { x++; - if (!switch_strlen_zero(local_argv[x])) { - SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(local_argv[x]) + 1); - if (!SWITCH_GLOBAL_dirs.run_dir) { - fprintf(stderr, "Allocation error\n"); - return 255; - } - strcpy(SWITCH_GLOBAL_dirs.run_dir, local_argv[x]); - run_set++; - } else { + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -run you must specify a pid directory\n"); return 255; } - known_opt++; + + SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.run_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.run_dir, local_argv[x]); + run_set = SWITCH_TRUE; } - if (local_argv[x] && !strcmp(local_argv[x], "-db")) { + else if (!strcmp(local_argv[x], "-db")) { x++; - if (!switch_strlen_zero(local_argv[x])) { - SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(strlen(local_argv[x]) + 1); - if (!SWITCH_GLOBAL_dirs.db_dir) { - fprintf(stderr, "Allocation error\n"); - return 255; - } - strcpy(SWITCH_GLOBAL_dirs.db_dir, local_argv[x]); - alt_dirs++; - } else { + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -db you must specify a db directory\n"); return 255; } - known_opt++; + + SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.db_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.db_dir, local_argv[x]); + alt_dirs++; } - if (local_argv[x] && !strcmp(local_argv[x], "-scripts")) { + else if (!strcmp(local_argv[x], "-scripts")) { x++; - if (!switch_strlen_zero(local_argv[x])) { - SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(strlen(local_argv[x]) + 1); - if (!SWITCH_GLOBAL_dirs.script_dir) { - fprintf(stderr, "Allocation error\n"); - return 255; - } - strcpy(SWITCH_GLOBAL_dirs.script_dir, local_argv[x]); - } else { + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -scripts you must specify a scripts directory\n"); return 255; } - known_opt++; + + SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.script_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.script_dir, local_argv[x]); } - if (local_argv[x] && !strcmp(local_argv[x], "-htdocs")) { + else if (!strcmp(local_argv[x], "-htdocs")) { x++; - if (!switch_strlen_zero(local_argv[x])) { - SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(strlen(local_argv[x]) + 1); - if (!SWITCH_GLOBAL_dirs.htdocs_dir) { - fprintf(stderr, "Allocation error\n"); - return 255; - } - strcpy(SWITCH_GLOBAL_dirs.htdocs_dir, local_argv[x]); - } else { + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -htdocs you must specify a htdocs directory\n"); return 255; } - known_opt++; - } - if (!known_opt) { + SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.htdocs_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.htdocs_dir, local_argv[x]); + } + /* Unknown option (always last!) */ + else { fprintf(stderr, "Unknown option '%s', see '%s -help' for a list of valid options\n", local_argv[x], local_argv[0]); exit(EXIT_FAILURE); @@ -879,21 +872,20 @@ int main(int argc, char *argv[]) } #else if (win32_service) { - { /* Attempt to start service */ - SERVICE_TABLE_ENTRY dispatchTable[] = { - {service_name, &service_main} - , - {NULL, NULL} - }; - service_flags = flags; /* copy parsed flags for service startup */ + /* Attempt to start service */ + SERVICE_TABLE_ENTRY dispatchTable[] = { + {service_name, &service_main} + , + {NULL, NULL} + }; + service_flags = flags; /* copy parsed flags for service startup */ - if (StartServiceCtrlDispatcher(dispatchTable) == 0) { - /* Not loaded as a service */ - fprintf(stderr, "Error Freeswitch loaded as a console app with -service option\n"); - fprintf(stderr, "To install the service load freeswitch with -install\n"); - } - exit(0); + if (StartServiceCtrlDispatcher(dispatchTable) == 0) { + /* Not loaded as a service */ + fprintf(stderr, "Error Freeswitch loaded as a console app with -service option\n"); + fprintf(stderr, "To install the service load freeswitch with -install\n"); } + exit(EXIT_SUCCESS); } #endif From b494d46f45728a9d54b1640a3c0d92abca680546 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 11 Jul 2012 00:11:59 +0200 Subject: [PATCH 09/16] freeswitch: Clean up daemonize(). Whitespace and indentation clean up. Use EXIT_SUCESS/_FAILURE. Signed-off-by: Stefan Knoblich --- src/switch.c | 73 ++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/src/switch.c b/src/switch.c index 5edccd10b2..d4f8b1b42c 100644 --- a/src/switch.c +++ b/src/switch.c @@ -236,75 +236,68 @@ void WINAPI service_main(DWORD numArgs, char **args) #else -void daemonize(int do_wait) +static void daemonize(int do_wait) { int fd; pid_t pid; if (!do_wait) { switch (fork()) { - case 0: + case 0: /* child process */ break; case -1: fprintf(stderr, "Error Backgrounding (fork)! %d - %s\n", errno, strerror(errno)); - exit(0); + exit(EXIT_SUCCESS); break; - default: - exit(0); + default: /* parent process */ + exit(EXIT_SUCCESS); } if (setsid() < 0) { fprintf(stderr, "Error Backgrounding (setsid)! %d - %s\n", errno, strerror(errno)); - exit(0); + exit(EXIT_SUCCESS); } } pid = fork(); switch (pid) { - case 0: + case 0: /* child process */ break; case -1: fprintf(stderr, "Error Backgrounding (fork2)! %d - %s\n", errno, strerror(errno)); - exit(0); + exit(EXIT_SUCCESS); break; - default: - { - fprintf(stderr, "%d Backgrounding.\n", (int) pid); + default: /* parent process */ + fprintf(stderr, "%d Backgrounding.\n", (int) pid); + if (do_wait) { + unsigned int sanity = 60; + char *o; - if (do_wait) { - unsigned int sanity = 60; - char *o; - - if ((o = getenv("FREESWITCH_BG_TIMEOUT"))) { - int tmp = atoi(o); - if (tmp > 0) { - sanity = tmp; - } + if ((o = getenv("FREESWITCH_BG_TIMEOUT"))) { + int tmp = atoi(o); + if (tmp > 0) { + sanity = tmp; } - - while(--sanity && !system_ready) { - - if (sanity % 2 == 0) { - printf("FreeSWITCH[%d] Waiting for background process pid:%d to be ready.....\n", (int)getpid(), (int) pid); - } - sleep(1); - } - - if (system_ready == 1) { - printf("FreeSWITCH[%d] System Ready pid:%d\n", (int) getpid(), (int) pid); - } else { - printf("FreeSWITCH[%d] Error starting system! pid:%d\n", (int)getpid(), (int) pid); - kill(pid, 9); - exit(-1); - } - } - } + while (--sanity && !system_ready) { - exit(0); + if (sanity % 2 == 0) { + printf("FreeSWITCH[%d] Waiting for background process pid:%d to be ready.....\n", (int)getpid(), (int) pid); + } + sleep(1); + } + if (!system_ready) { + printf("FreeSWITCH[%d] Error starting system! pid:%d\n", (int)getpid(), (int) pid); + kill(pid, 9); + exit(EXIT_FAILURE); + } + + printf("FreeSWITCH[%d] System Ready pid:%d\n", (int) getpid(), (int) pid); + } + exit(EXIT_SUCCESS); } if (do_wait) { @@ -317,11 +310,13 @@ void daemonize(int do_wait) dup2(fd, 0); close(fd); } + fd = open("/dev/null", O_WRONLY); if (fd != 1) { dup2(fd, 1); close(fd); } + fd = open("/dev/null", O_WRONLY); if (fd != 2) { dup2(fd, 2); From 93a429fc11ffece1cde64dd57da5bbfeb4a59436 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 11 Jul 2012 00:12:57 +0200 Subject: [PATCH 10/16] freeswitch: Whitespace clean up in switch.c. Signed-off-by: Stefan Knoblich --- src/switch.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/switch.c b/src/switch.c index d4f8b1b42c..7ef7a157df 100644 --- a/src/switch.c +++ b/src/switch.c @@ -1,4 +1,4 @@ -/* +/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * Copyright (C) 2005-2012, Anthony Minessale II * @@ -22,7 +22,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * + * * Anthony Minessale II * Michael Jerris * Pawel Pierscionek @@ -100,7 +100,6 @@ static void handle_SIGCHLD(int sig) if (sig) {}; pid = wait(&status); - if (pid > 0) { system_ready = -1; } @@ -798,28 +797,27 @@ int main(int argc, char *argv[]) if (rlp.rlim_cur != SWITCH_THREAD_STACKSIZE) { char buf[1024] = ""; int i = 0; + fprintf(stderr, "Error: stacksize %d is not optimal: run ulimit -s %d from your shell before starting the application.\nauto-adjusting stack size for optimal performance...\n", (int) (rlp.rlim_cur / 1024), SWITCH_THREAD_STACKSIZE / 1024); - + memset(&rlp, 0, sizeof(rlp)); rlp.rlim_cur = SWITCH_THREAD_STACKSIZE; rlp.rlim_max = SWITCH_THREAD_STACKSIZE; setrlimit(RLIMIT_STACK, &rlp); - + apr_terminate(); ret = (int) execv(argv[0], argv); - + for (i = 0; i < argc; i++) { switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s ", argv[i]); } - - return system(buf); + return system(buf); } } #endif - signal(SIGILL, handle_SIGILL); signal(SIGTERM, handle_SIGILL); #ifndef WIN32 @@ -828,7 +826,7 @@ int main(int argc, char *argv[]) signal(SIGCHLD, handle_SIGCHLD); } #endif - + if (nc) { #ifdef WIN32 FreeConsole(); @@ -839,8 +837,7 @@ int main(int argc, char *argv[]) #endif } - - switch(priority) { + switch (priority) { case 2: set_realtime_priority(); break; From edfbbb127cfc16f32b519a6c9f8233db7f37449e Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 11 Jul 2012 00:14:01 +0200 Subject: [PATCH 11/16] freeswitch: Create struct rlimit rlp where it is needed (move down into block scope). Signed-off-by: Stefan Knoblich --- src/switch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/switch.c b/src/switch.c index 7ef7a157df..fc076fe709 100644 --- a/src/switch.c +++ b/src/switch.c @@ -416,7 +416,6 @@ int main(int argc, char *argv[]) switch_file_t *fd; switch_memory_pool_t *pool = NULL; #ifdef HAVE_SETRLIMIT - struct rlimit rlp; switch_bool_t waste = SWITCH_FALSE; #endif @@ -573,6 +572,7 @@ int main(int argc, char *argv[]) #endif #ifdef HAVE_SETRLIMIT else if (!strcmp(local_argv[x], "-core")) { + struct rlimit rlp; memset(&rlp, 0, sizeof(rlp)); rlp.rlim_cur = RLIM_INFINITY; rlp.rlim_max = RLIM_INFINITY; @@ -789,7 +789,7 @@ int main(int argc, char *argv[]) #if defined(HAVE_SETRLIMIT) && !defined(__sun) if (!waste && !(flags & SCF_VG)) { - //int x; + struct rlimit rlp; memset(&rlp, 0, sizeof(rlp)); getrlimit(RLIMIT_STACK, &rlp); From aeb4b31063e5378dbd41061b488f0daa8f8fb190 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 11 Jul 2012 00:16:21 +0200 Subject: [PATCH 12/16] freeswitch: Show user/group name in error message if change_user_group() fails. Signed-off-by: Stefan Knoblich --- src/switch.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/switch.c b/src/switch.c index fc076fe709..93ae47cfd5 100644 --- a/src/switch.c +++ b/src/switch.c @@ -858,7 +858,9 @@ int main(int argc, char *argv[]) #ifndef WIN32 if (runas_user || runas_group) { if (change_user_group(runas_user, runas_group) < 0) { - fprintf(stderr, "Failed to switch user / group\n"); + fprintf(stderr, "Failed to switch user [%s] / group [%s]\n", + switch_strlen_zero(runas_user) ? "-" : runas_user, + switch_strlen_zero(runas_group) ? "-" : runas_group); return 255; } } From 07e9467d351d42aabb19c7e5717308b06df0529a Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 11 Jul 2012 00:50:46 +0200 Subject: [PATCH 13/16] freeswitch: Add more cmdline options to control file locations. Setting the base_dir variable didn't work so this will have to be enough for now. Signed-off-by: Stefan Knoblich --- src/switch.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 7 deletions(-) diff --git a/src/switch.c b/src/switch.c index 93ae47cfd5..4410d75fb5 100644 --- a/src/switch.c +++ b/src/switch.c @@ -360,13 +360,19 @@ static const char const usage[] = "\t-ncwait -- do not output to a console and background but wait until the system is ready before exiting (implies -nc)\n" #endif "\t-c -- output to a console and stay in the foreground\n" - "\t-conf [confdir] -- specify an alternate config dir\n" - "\t-log [logdir] -- specify an alternate log dir\n" - "\t-run [rundir] -- specify an alternate run dir\n" - "\t-db [dbdir] -- specify an alternate db dir\n" - "\t-mod [moddir] -- specify an alternate mod dir\n" - "\t-htdocs [htdocsdir] -- specify an alternate htdocs dir\n" - "\t-scripts [scriptsdir] -- specify an alternate scripts dir\n"; + "\n\tOptions to control locations of files:\n" + "\t-conf [confdir] -- alternate directory for FreeSWITCH configuration files\n" + "\t-log [logdir] -- alternate directory for logfiles\n" + "\t-run [rundir] -- alternate directory for runtime files\n" + "\t-db [dbdir] -- alternate directory for the internal database\n" + "\t-mod [moddir] -- alternate directory for modules\n" + "\t-htdocs [htdocsdir] -- alternate directory for htdocs\n" + "\t-scripts [scriptsdir] -- alternate directory for scripts\n" + "\t-temp [directory] -- alternate directory for temporary files\n" + "\t-grammar [directory] -- alternate directory for grammar files\n" + "\t-recordings [directory] -- alternate directory for recordings\n" + "\t-storage [directory] -- alternate directory for voicemail storage\n" + "\t-sounds [directory] -- alternate directory for sound files\n"; /** @@ -755,6 +761,82 @@ int main(int argc, char *argv[]) } strcpy(SWITCH_GLOBAL_dirs.htdocs_dir, local_argv[x]); } + + else if (!strcmp(local_argv[x], "-temp")) { + x++; + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { + fprintf(stderr, "When using -temp you must specify a temp directory\n"); + return 255; + } + + SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.temp_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.temp_dir, local_argv[x]); + } + + else if (!strcmp(local_argv[x], "-storage")) { + x++; + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { + fprintf(stderr, "When using -storage you must specify a storage directory\n"); + return 255; + } + + SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.storage_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.storage_dir, local_argv[x]); + } + + else if (!strcmp(local_argv[x], "-recordings")) { + x++; + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { + fprintf(stderr, "When using -recordings you must specify a recording directory\n"); + return 255; + } + + SWITCH_GLOBAL_dirs.recordings_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.recordings_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.recordings_dir, local_argv[x]); + } + + else if (!strcmp(local_argv[x], "-grammar")) { + x++; + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { + fprintf(stderr, "When using -grammar you must specify a grammar directory\n"); + return 255; + } + + SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.grammar_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.grammar_dir, local_argv[x]); + } + + else if (!strcmp(local_argv[x], "-sounds")) { + x++; + if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { + fprintf(stderr, "When using -sounds you must specify a sounds directory\n"); + return 255; + } + + SWITCH_GLOBAL_dirs.sounds_dir = (char *) malloc(strlen(local_argv[x]) + 1); + if (!SWITCH_GLOBAL_dirs.sounds_dir) { + fprintf(stderr, "Allocation error\n"); + return 255; + } + strcpy(SWITCH_GLOBAL_dirs.sounds_dir, local_argv[x]); + } + /* Unknown option (always last!) */ else { fprintf(stderr, "Unknown option '%s', see '%s -help' for a list of valid options\n", From 91236c9ad3e9e637d8047cc3effe1f94085f985e Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 11 Jul 2012 07:52:20 -0500 Subject: [PATCH 14/16] fix build related issues on windows - trivial --- src/switch.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/switch.c b/src/switch.c index 4410d75fb5..c8342257c2 100644 --- a/src/switch.c +++ b/src/switch.c @@ -68,6 +68,10 @@ static switch_core_flag_t service_flags = SCF_NONE; /* event to signal shutdown (for you unix people, this is like a pthread_cond) */ static HANDLE shutdown_event; + +#ifndef PATH_MAX +#define PATH_MAX 256 +#endif #endif /* signal handler for when freeswitch is running in background mode. @@ -325,7 +329,7 @@ static void daemonize(int do_wait) #endif -static const char const usage[] = +static const char usage[] = "Usage: freeswitch [OPTIONS]\n\n" "These are the optional arguments you can pass to freeswitch:\n" #ifdef WIN32 From 61cfafe6c2866c75f64466697f10315bca173663 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 11 Jul 2012 17:21:49 +0200 Subject: [PATCH 15/16] FreeTDM: Move custom backtrace code into ftdm_backtrace_walk() and helper functions. Portability fix for uClibc and other (linux) environments that lack execinfo.h. ftdm_backtrace_walk() and related return FTDM_NOTIMPL and print a message if backtraces are not available in the current environment. Signed-off-by: Stefan Knoblich --- libs/freetdm/Makefile.am | 3 +- libs/freetdm/configure.ac | 2 +- libs/freetdm/mod_freetdm/mod_freetdm.c | 40 +++++------ libs/freetdm/src/ftdm_backtrace.c | 75 ++++++++++++++++++++ libs/freetdm/src/include/freetdm.h | 34 +++++++++ libs/freetdm/src/include/private/ftdm_core.h | 4 -- 6 files changed, 132 insertions(+), 26 deletions(-) create mode 100644 libs/freetdm/src/ftdm_backtrace.c diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index bfd68a17eb..55d8865dec 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -79,7 +79,8 @@ libfreetdm_la_SOURCES = \ $(SRC)/ftdm_buffer.c \ $(SRC)/ftdm_threadmutex.c \ $(SRC)/ftdm_dso.c \ - $(SRC)/ftdm_cpu_monitor.c + $(SRC)/ftdm_cpu_monitor.c \ + $(SRC)/ftdm_backtrace.c library_include_HEADERS = \ $(SRC)/include/freetdm.h \ diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index b4c9cda8ab..f72a6268a8 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -136,7 +136,7 @@ AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([m], [cos]) -AC_CHECK_HEADERS([netdb.h sys/select.h]) +AC_CHECK_HEADERS([netdb.h sys/select.h execinfo.h]) AC_CHECK_FUNC([gethostbyname_r], [], [AC_CHECK_LIB([nsl], [gethostbyname_r])] diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 35b8d9b01a..64d34f232c 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -35,13 +35,6 @@ #include "freetdm.h" //#define CUDATEL_DEBUG -#ifdef CUDATEL_DEBUG -#ifndef _BSD_SOURCE -#define _BSD_SOURCE -#endif -#include -#include -#endif #ifndef __FUNCTION__ #define __FUNCTION__ __SWITCH_FUNC__ @@ -499,6 +492,21 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session) return SWITCH_STATUS_SUCCESS; } +#ifdef CUDATEL_DEBUG +struct cudatel_trace_priv { + const char *name; + int span_id; + int chan_id; +}; + +static void cudatel_trace(const int tid, const void *addr, const char *symbol, void *priv) +{ + struct cudatel_trace_priv *data = priv; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d][tid:%d] %s -> %s\n", + data->span_id, data->chan_id, tid, data->name, symbol); +} +#endif + static switch_status_t channel_on_hangup(switch_core_session_t *session) { switch_channel_t *channel = NULL; @@ -558,19 +566,11 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) #ifdef CUDATEL_DEBUG { - pid_t tid = 0; - size_t size = 0; - char **symbols = NULL; - void *stacktrace[50]; - int si = 0; - size = backtrace(stacktrace, ftdm_array_len(stacktrace)); - symbols = backtrace_symbols(stacktrace, size); - tid = syscall(SYS_gettid); - for (si = 0; si < size; si++) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d][tid:%d] %s -> %s\n", - span_id, chan_id, tid, name, symbols[si]); - } - free(symbols); + struct cudatel_trace_priv trace_data; + trace_data.name = name; + trace_data.span_id = span_id; + trace_data.chan_id = chan_id; + ftdm_backtrace_walk(&cudatel_trace, &trace_data); } #endif diff --git a/libs/freetdm/src/ftdm_backtrace.c b/libs/freetdm/src/ftdm_backtrace.c new file mode 100644 index 0000000000..70eef159d1 --- /dev/null +++ b/libs/freetdm/src/ftdm_backtrace.c @@ -0,0 +1,75 @@ +/* + * + * + */ +#define _BSD_SOURCE +#include "private/ftdm_core.h" + +#ifdef HAVE_EXECINFO_H +#include +#include +#include +#include + +#define FTDM_BACKTRACE_MAX 50 + +FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv) +{ + void *stacktrace[FTDM_BACKTRACE_MAX]; + char **symbols = NULL; + size_t size = 0; + pid_t tid = 0; + int si = 0; + + if (!callback) { + return FTDM_EINVAL; + } + + tid = syscall(SYS_gettid); + + size = backtrace(stacktrace, ftdm_array_len(stacktrace)); + symbols = backtrace_symbols(stacktrace, size); + + for (si = 0; si < size; si++) { + callback(tid, stacktrace[si], symbols[si], priv); + } + + free(symbols); + return FTDM_SUCCESS; +} + +#else /* !HAVE_EXECINFO_H */ + +FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv) +{ + ftdm_log(FTDM_LOG_DEBUG, "Stack traces are not available on this platform!\n"); + return FTDM_NOTIMPL; +} + +#endif + + +static void span_backtrace(const int tid, const void *addr, const char *symbol, void *priv) +{ + ftdm_span_t *span = priv; + ftdm_log(FTDM_LOG_DEBUG, "[%d][tid:%d] %p -> %s\n", + ftdm_span_get_id(span), tid, addr, symbol); +} + +FT_DECLARE(ftdm_status_t) ftdm_backtrace_span(ftdm_span_t *span) +{ + return ftdm_backtrace_walk(&span_backtrace, span); +} + + +static void chan_backtrace(const int tid, const void *addr, const char *symbol, void *priv) +{ + ftdm_channel_t *chan = priv; + ftdm_log(FTDM_LOG_DEBUG, "[%d:%d][tid:%d] %p -> %s\n", + ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan), tid, addr, symbol); +} + +FT_DECLARE(ftdm_status_t) ftdm_backtrace_chan(ftdm_channel_t *chan) +{ + return ftdm_backtrace_walk(&chan_backtrace, chan); +} diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index b178784239..d984f5b1c8 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -1814,6 +1814,40 @@ FT_DECLARE(void) ftdm_global_set_config_directory(const char *path); /*! \brief Check if the FTDM library is initialized and running */ FT_DECLARE(ftdm_bool_t) ftdm_running(void); +/** + * Generate a stack trace and invoke a callback function for each entry + * \param[in] callback Callback function, that is invoked for each stack symbol + * \param[in] priv (User-)Private data passed to the callback + * \retval + * FTDM_SUCCESS On success + * FTDM_NOTIMPL Backtraces are not available + * FTDM_EINVAL Invalid arguments (callback was NULL) + */ +FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv); + +/** + * Convenience function to print a backtrace for a span. + * \note The backtrace is generated with FTDM_LOG_DEBUG log level. + * \param[in] span Span object + * \retval + * FTDM_SUCCESS On success + * FTDM_NOTIMPL Backtraces are not available + * FTDM_EINVAL Invalid arguments (e.g. span was NULL) + */ +FT_DECLARE(ftdm_status_t) ftdm_backtrace_span(ftdm_span_t *span); + +/** + * Convenience function to print a backtrace for a channel. + * \note The backtrace is generated with FTDM_LOG_DEBUG log level. + * \param[in] chan Channel object + * \retval + * FTDM_SUCCESS On success + * FTDM_NOTIMPL Backtraces are not available + * FTDM_EINVAL Invalid arguments (e.g. chan was NULL) + */ +FT_DECLARE(ftdm_status_t) ftdm_backtrace_chan(ftdm_channel_t *chan); + + FT_DECLARE_DATA extern ftdm_logger_t ftdm_log; /*! \brief Basic transcoding function prototype */ diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 6418baa3be..7cd8aacafb 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -104,10 +104,6 @@ #include #endif -#ifdef __linux__ -#include -#endif - #include #include #include From 7a12804577e87c6297b581532d7404f0ed450ec8 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 11 Jul 2012 19:15:35 +0200 Subject: [PATCH 16/16] FreeTDM: Add trunk mode (NET/CPE) to span configuration in freetdm.conf and use it in ftmod_misdn and ftmod_libpri. Some I/O implementations (e.g. mISDN) need this information to correctly set up the port configuration. In FreeTDM, the mode of a span has been. up until now, a part of the signalling module configuration ("node" or "mode" for libpri and isdn spans), which is parsed _after_ the I/O part of a span has been initialized. This limitation currently prevents us from using mISDN in NT mode. To work around this problem (without adding a lot of new tunk_type values like "E1_NET" etc.), add a new "trunk_mode" parameter to the span categories in freetdm.conf, which by default is "CPE" for all trunk types, except "FXS" (which defaults to "NET"). ftmod_misdn uses trunk_type + trunk_mode to correctly choose the d-channel protocol for a port. ftmod_libpri uses trunk_mode as a hint for the default "mode" setting. (NOTE: It will print a warning if trunk_mode and signalling mode do not match.) All other modules currently ignore the value of trunk_mode. Example freetdm.conf snippet for a mISDN span in NET/NT mode (using a HFC-S USB dongle): [span misdn MBRI_1] trunk_type => BRI_PTMP trunk_mode => NET b-channel => HFC-S_USB.1:1-2 d-channel => HFC-S_USB.1:3 Signed-off-by: Stefan Knoblich --- libs/freetdm/src/ftdm_io.c | 42 +++++++++++++++---- .../src/ftmod/ftmod_libpri/ftmod_libpri.c | 22 ++++++++-- .../src/ftmod/ftmod_misdn/ftmod_misdn.c | 4 +- libs/freetdm/src/include/freetdm.h | 36 +++++++++++++++- libs/freetdm/src/include/private/ftdm_core.h | 1 + 5 files changed, 91 insertions(+), 14 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index ab015b98ff..4b49a9156c 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -262,9 +262,12 @@ FTDM_STR2ENUM(ftdm_str2ftdm_tonemap, ftdm_tonemap2str, ftdm_tonemap_t, TONEMAP_N FTDM_ENUM_NAMES(OOB_NAMES, OOB_STRINGS) FTDM_STR2ENUM(ftdm_str2ftdm_oob_event, ftdm_oob_event2str, ftdm_oob_event_t, OOB_NAMES, FTDM_OOB_INVALID) -FTDM_ENUM_NAMES(TRUNK_TYPE_NAMES, TRUNK_STRINGS) +FTDM_ENUM_NAMES(TRUNK_TYPE_NAMES, TRUNK_TYPE_STRINGS) FTDM_STR2ENUM(ftdm_str2ftdm_trunk_type, ftdm_trunk_type2str, ftdm_trunk_type_t, TRUNK_TYPE_NAMES, FTDM_TRUNK_NONE) +FTDM_ENUM_NAMES(TRUNK_MODE_NAMES, TRUNK_MODE_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_trunk_mode, ftdm_trunk_mode2str, ftdm_trunk_mode_t, TRUNK_MODE_NAMES, FTDM_TRUNK_MODE_INVALID) + FTDM_ENUM_NAMES(START_TYPE_NAMES, START_TYPE_STRINGS) FTDM_STR2ENUM(ftdm_str2ftdm_analog_start_type, ftdm_analog_start_type2str, ftdm_analog_start_type_t, START_TYPE_NAMES, FTDM_ANALOG_START_NA) @@ -816,6 +819,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_create(const char *iotype, const char *name, ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_BUSY], "%(500,500,480,620)", FTDM_TONEMAP_LEN); ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_ATTN], "%(100,100,1400,2060,2450,2600)", FTDM_TONEMAP_LEN); new_span->trunk_type = FTDM_TRUNK_NONE; + new_span->trunk_mode = FTDM_TRUNK_MODE_CPE; new_span->data_type = FTDM_TYPE_SPAN; ftdm_mutex_lock(globals.span_mutex); @@ -1994,6 +1998,21 @@ FT_DECLARE(const char *) ftdm_span_get_trunk_type_str(const ftdm_span_t *span) return ftdm_trunk_type2str(span->trunk_type); } +FT_DECLARE(void) ftdm_span_set_trunk_mode(ftdm_span_t *span, ftdm_trunk_mode_t mode) +{ + span->trunk_mode = mode; +} + +FT_DECLARE(ftdm_trunk_mode_t) ftdm_span_get_trunk_mode(const ftdm_span_t *span) +{ + return span->trunk_mode; +} + +FT_DECLARE(const char *) ftdm_span_get_trunk_mode_str(const ftdm_span_t *span) +{ + return ftdm_trunk_mode2str(span->trunk_mode); +} + FT_DECLARE(uint32_t) ftdm_span_get_id(const ftdm_span_t *span) { return span->span_id; @@ -4706,6 +4725,10 @@ static ftdm_status_t load_config(void) ftdm_trunk_type_t trtype = ftdm_str2ftdm_trunk_type(val); ftdm_span_set_trunk_type(span, trtype); ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s'\n", ftdm_trunk_type2str(trtype)); + } else if (!strcasecmp(var, "trunk_mode")) { + ftdm_trunk_mode_t trmode = ftdm_str2ftdm_trunk_mode(val); + ftdm_span_set_trunk_mode(span, trmode); + ftdm_log(FTDM_LOG_DEBUG, "setting trunk mode to '%s'\n", ftdm_trunk_mode2str(trmode)); } else if (!strcasecmp(var, "name")) { if (!strcasecmp(val, "undef")) { chan_config.name[0] = '\0'; @@ -4729,9 +4752,10 @@ static ftdm_status_t load_config(void) } } else if (!strcasecmp(var, "fxo-channel")) { if (span->trunk_type == FTDM_TRUNK_NONE) { - span->trunk_type = FTDM_TRUNK_FXO; - ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", ftdm_trunk_type2str(span->trunk_type), - ftdm_analog_start_type2str(span->start_type)); + span->trunk_type = FTDM_TRUNK_FXO; + span->trunk_mode = FTDM_TRUNK_MODE_CPE; + ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s), mode(%s)\n", ftdm_trunk_type2str(span->trunk_type), + ftdm_analog_start_type2str(span->start_type), ftdm_trunk_mode2str(span->trunk_mode)); } if (span->trunk_type == FTDM_TRUNK_FXO) { unsigned chans_configured = 0; @@ -4745,8 +4769,9 @@ static ftdm_status_t load_config(void) } else if (!strcasecmp(var, "fxs-channel")) { if (span->trunk_type == FTDM_TRUNK_NONE) { span->trunk_type = FTDM_TRUNK_FXS; - ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", ftdm_trunk_type2str(span->trunk_type), - ftdm_analog_start_type2str(span->start_type)); + span->trunk_mode = FTDM_TRUNK_MODE_NET; + ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s), mode(%s)\n", ftdm_trunk_type2str(span->trunk_type), + ftdm_analog_start_type2str(span->start_type), ftdm_trunk_mode2str(span->trunk_mode)); } if (span->trunk_type == FTDM_TRUNK_FXS) { unsigned chans_configured = 0; @@ -4760,8 +4785,9 @@ static ftdm_status_t load_config(void) } else if (!strcasecmp(var, "em-channel")) { if (span->trunk_type == FTDM_TRUNK_NONE) { span->trunk_type = FTDM_TRUNK_EM; - ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", ftdm_trunk_type2str(span->trunk_type), - ftdm_analog_start_type2str(span->start_type)); + span->trunk_mode = FTDM_TRUNK_MODE_CPE; + ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s), mode(%s)\n", ftdm_trunk_type2str(span->trunk_type), + ftdm_analog_start_type2str(span->start_type), ftdm_trunk_mode2str(span->trunk_mode)); } if (span->trunk_type == FTDM_TRUNK_EM) { unsigned chans_configured = 0; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index ecd1cff1d3..471b870f34 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -2462,9 +2462,15 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span) memset(isdn_data, 0, sizeof(*isdn_data)); /* set some default values */ - isdn_data->mode = PRI_CPE; isdn_data->ton = PRI_UNKNOWN; + /* Use span's trunk_mode as a reference for the default libpri mode */ + if (ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET) { + isdn_data->mode = PRI_NETWORK; + } else { + isdn_data->mode = PRI_CPE; + } + switch (ftdm_span_get_trunk_type(span)) { case FTDM_TRUNK_BRI: case FTDM_TRUNK_BRI_PTMP: @@ -2516,8 +2522,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span) if (!strcasecmp(var, "node") || !strcasecmp(var, "mode")) { if ((isdn_data->mode = parse_mode(val)) == -1) { - ftdm_log(FTDM_LOG_ERROR, "Unknown node type '%s', defaulting to CPE mode\n", val); - isdn_data->mode = PRI_CPE; + ftdm_log(FTDM_LOG_ERROR, "Unknown node type '%s'\n", val); + goto error; } } else if (!strcasecmp(var, "switch") || !strcasecmp(var, "dialect")) { @@ -2563,6 +2569,16 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span) } } + /* Check if modes match and log a message if they do not. Just to be on the safe side. */ + if (isdn_data->mode == PRI_CPE && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET) { + ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for TE/CPE/USER mode, while port is running in NT/NET mode. You may want to check your 'trunk_mode' settings.\n", + ftdm_span_get_name(span)); + } + else if (isdn_data->mode == PRI_NETWORK && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_CPE) { + ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for NT/NET mode, while port is running in TE/CPE/USER mode. You may want to check your 'trunk_mode' settings.\n", + ftdm_span_get_name(span)); + } + span->start = ftdm_libpri_start; span->stop = ftdm_libpri_stop; span->signal_cb = sig_cb; diff --git a/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c b/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c index 60e3c1425d..c304a8b37b 100644 --- a/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c +++ b/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c @@ -1432,12 +1432,12 @@ static ftdm_status_t misdn_open_range(ftdm_span_t *span, ftdm_chan_type_t type, switch (ftdm_span_get_trunk_type(span)) { case FTDM_TRUNK_E1: - d_protocol = ISDN_P_TE_E1; + d_protocol = ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET ? ISDN_P_NT_E1 : ISDN_P_TE_E1; d_channel = 16; break; case FTDM_TRUNK_BRI: case FTDM_TRUNK_BRI_PTMP: - d_protocol = ISDN_P_TE_S0; + d_protocol = ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET ? ISDN_P_NT_S0 : ISDN_P_TE_S0; d_channel = 0; break; default: diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index d984f5b1c8..809465c47a 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -484,11 +484,23 @@ typedef enum { FTDM_TRUNK_GSM, FTDM_TRUNK_NONE } ftdm_trunk_type_t; -#define TRUNK_STRINGS "E1", "T1", "J1", "BRI", "BRI_PTMP", "FXO", "FXS", "EM", "GSM", "NONE" +#define TRUNK_TYPE_STRINGS "E1", "T1", "J1", "BRI", "BRI_PTMP", "FXO", "FXS", "EM", "GSM", "NONE" /*! \brief Move from string to ftdm_trunk_type_t and viceversa */ FTDM_STR2ENUM_P(ftdm_str2ftdm_trunk_type, ftdm_trunk_type2str, ftdm_trunk_type_t) +/*! \brief Span trunk modes */ +typedef enum { + FTDM_TRUNK_MODE_CPE, + FTDM_TRUNK_MODE_NET, + FTDM_TRUNK_MODE_INVALID +} ftdm_trunk_mode_t; +#define TRUNK_MODE_STRINGS "CPE", "NET", "INVALID" + +/*! \brief Move from string to ftdm_trunk_mode_t and viceversa */ +FTDM_STR2ENUM_P(ftdm_str2ftdm_trunk_mode, ftdm_trunk_mode2str, ftdm_trunk_mode_t) + + /*! \brief Basic channel configuration provided to ftdm_configure_span_channels */ typedef struct ftdm_channel_config { char name[FTDM_MAX_NAME_STR_SZ]; @@ -1744,6 +1756,28 @@ FT_DECLARE(ftdm_trunk_type_t) ftdm_span_get_trunk_type(const ftdm_span_t *span); /*! \brief For display debugging purposes you can display this string which describes the trunk type of a span */ FT_DECLARE(const char *) ftdm_span_get_trunk_type_str(const ftdm_span_t *span); +/*! + * Set the trunk mode for a span + * \note This must be called before configuring any channels within the span! + * \param[in] span The span + * \param[in] type The trunk mode + */ +FT_DECLARE(void) ftdm_span_set_trunk_mode(ftdm_span_t *span, ftdm_trunk_mode_t mode); + +/*! + * Get the trunk mode for a span + * \param[in] span The span + * \return Span trunk mode + */ +FT_DECLARE(ftdm_trunk_mode_t) ftdm_span_get_trunk_mode(const ftdm_span_t *span); + +/*! + * Get the trunk mode of a span in textual form + * \param[in] span The span + * \return Span mode name as a string + */ +FT_DECLARE(const char *) ftdm_span_get_trunk_mode_str(const ftdm_span_t *span); + /*! * \brief Return the channel identified by the provided id * diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 7cd8aacafb..fa1bd233cd 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -485,6 +485,7 @@ struct ftdm_span { fio_event_cb_t event_callback; ftdm_mutex_t *mutex; ftdm_trunk_type_t trunk_type; + ftdm_trunk_mode_t trunk_mode; ftdm_analog_start_type_t start_type; ftdm_signal_type_t signal_type; uint32_t last_used_index;