diff --git a/daemon/main.c b/daemon/main.c index 94951544e..95fc70f12 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -265,6 +265,8 @@ static int redis_ep_parse(endpoint_t *ep, int *db, char **auth, const char *auth static void options(int *argc, char ***argv) { + char *configfile = NULL; + char *configsection = "rtpengine"; char **if_a = NULL; char **ks_a = NULL; unsigned int uint_keyspace_db; @@ -289,6 +291,8 @@ static void options(int *argc, char ***argv) { char *endptr; GOptionEntry e[] = { + { "config-file", 0, 0, G_OPTION_ARG_STRING, &configfile, "Load config from this file", "FILE" }, + { "config-section",0,0, G_OPTION_ARG_STRING, &configsection, "Config file section to use", "STRING" }, { "version", 'v', 0, G_OPTION_ARG_NONE, &version, "Print build time and exit", NULL }, { "table", 't', 0, G_OPTION_ARG_INT, &table, "Kernel table to use", "INT" }, { "no-fallback",'F', 0, G_OPTION_ARG_NONE, &no_fallback, "Only start when kernel module is available", NULL }, @@ -335,13 +339,11 @@ static void options(int *argc, char ***argv) { { NULL, } }; - GOptionContext *c; - GError *er = NULL; + const char *errstr = config_load(argc, argv, e, " - next-generation media proxy", &configfile, + "/etc/rtpengine/rtpengine.conf", &configsection); - c = g_option_context_new(" - next-generation media proxy"); - g_option_context_add_main_entries(c, e, NULL); - if (!g_option_context_parse(c, argc, argv, &er)) - die("Bad command line: %s", er->message); + if (errstr) + die("Bad command line: %s", errstr); if (version) die("%s", RTPENGINE_VERSION); diff --git a/daemon/recording.c b/daemon/recording.c index 7dd2cd5bd..0a6958dbd 100644 --- a/daemon/recording.c +++ b/daemon/recording.c @@ -152,16 +152,16 @@ found: } } -static int check_create_dir(const char *dir, const char *desc, int creat) { +static int check_create_dir(const char *dir, const char *desc, mode_t creat_mode) { struct stat info; if (stat(dir, &info) != 0) { - if (!creat) { + if (!creat_mode) { ilog(LOG_WARN, "%s directory \"%s\" does not exist.", desc, dir); return FALSE; } ilog(LOG_INFO, "Creating %s directory \"%s\".", desc, dir); - if (mkdir(dir, 0777) == 0) + if (mkdir(dir, creat_mode) == 0) return TRUE; ilog(LOG_ERR, "Failed to create %s directory \"%s\": %s", desc, dir, strerror(errno)); return FALSE; @@ -174,7 +174,7 @@ static int check_create_dir(const char *dir, const char *desc, int creat) { } static int check_main_spool_dir(const char *spoolpath) { - return check_create_dir(spoolpath, "spool", 0); + return check_create_dir(spoolpath, "spool", 0700); } /** @@ -201,11 +201,11 @@ static int pcap_create_spool_dir(const char *spoolpath) { snprintf(rec_path, sizeof(rec_path), "%s/pcaps", spoolpath); snprintf(tmp_path, sizeof(tmp_path), "%s/tmp", spoolpath); - if (!check_create_dir(meta_path, "metadata", 1)) + if (!check_create_dir(meta_path, "metadata", 0777)) spool_good = FALSE; - if (!check_create_dir(rec_path, "pcaps", 1)) + if (!check_create_dir(rec_path, "pcaps", 0777)) spool_good = FALSE; - if (!check_create_dir(tmp_path, "tmp", 1)) + if (!check_create_dir(tmp_path, "tmp", 0777)) spool_good = FALSE; return spool_good; diff --git a/debian/dirs b/debian/dirs index 236670a2d..1c63c5155 100644 --- a/debian/dirs +++ b/debian/dirs @@ -1 +1,2 @@ usr/sbin +etc/rtpengine diff --git a/debian/ngcp-rtpengine-daemon.default b/debian/ngcp-rtpengine-daemon.default index 3c59580ef..3c976f1b1 100644 --- a/debian/ngcp-rtpengine-daemon.default +++ b/debian/ngcp-rtpengine-daemon.default @@ -1,47 +1,4 @@ RUN_RTPENGINE=no -LISTEN_TCP=25060 -LISTEN_UDP=12222 -LISTEN_NG=22222 -LISTEN_CLI=9900 -# INTERFACES="123.234.345.456" -# INTERFACES="internal/12.23.34.45 external/23.34.45.54" -# INTERFACES="12.23.34.45!23.34.45.56" -TIMEOUT=60 -SILENT_TIMEOUT=3600 -# FINAL_TIMEOUT=10800 +CONFIG_FILE=/etc/rtpengine/rtpengine.conf +# CONFIG_SECTION=rtpengine PIDFILE=/var/run/ngcp-rtpengine-daemon.pid -FORK=yes -# TOS=184 -TABLE=0 -# NO_FALLBACK=yes -# PORT_MIN=30000 -# PORT_MAX=50000 -# REDIS=127.0.0.1:6379 -# REDIS_DB=1 -# REDIS_AUTH_PW=foobar -# REDIS_WRITE=127.0.0.1:6379 -# REDIS_WRITE_DB=1 -# REDIS_WRITE_AUTH_PW=foobar -# REDIS_NUM_THREADS=8 -# REDIS_EXPIRE=86400 -# NO_REDIS_REQUIRED=yes -# B2B_URL=http://127.0.0.1:8090/ -# LOG_LEVEL=6 -# LOG_FACILITY=daemon -# LOG_FACILITY_CDR=daemon -# LOG_FACILITY_RTCP=daemon -# NUM_THREADS=5 -# DELETE_DELAY=30 -# GRAPHITE=9006 -# GRAPHITE_INTERVAL=60 -# GRAPHITE_PREFIX=myownprefix. -# MAX_SESSIONS=5000 -# CREATE_IPTABLES_CHAIN=no -# HOMER=123.234.345.456:65432 -# HOMER_PROTOCOL=udp -# HOMER_ID=2001 -# RECORDING_DIR=/var/spool/rtpengine/ -# RECORDING_METHOD=proc -# RECORDING_FORMAT=eth -# LOG_STDERR="no" -# DTLS_PASSIVE="no" diff --git a/debian/ngcp-rtpengine-daemon.init b/debian/ngcp-rtpengine-daemon.init index 7512d60bf..8ec60fec7 100755 --- a/debian/ngcp-rtpengine-daemon.init +++ b/debian/ngcp-rtpengine-daemon.init @@ -56,6 +56,8 @@ if [ ! -z "$SUBSCRIBE_KEYSPACES" ]; then done fi +[ -z "$CONFIG_FILE" ] || OPTIONS="$OPTIONS --config-file=$CONFIG_FILE" +[ -z "$CONFIG_SECTION" ] || OPTIONS="$OPTIONS --config-section=$CONFIG_SECTION" [ -z "$ADDRESS" ] || OPTIONS="$OPTIONS --interface=$ADDRESS" [ -z "$ADV_ADDRESS" ] || OPTIONS="$OPTIONS!$ADV_ADDRESS" [ -z "$ADDRESS_IPV6" ] || OPTIONS="$OPTIONS --interface=$ADDRESS_IPV6" diff --git a/debian/ngcp-rtpengine-daemon.install b/debian/ngcp-rtpengine-daemon.install index ba2780462..eef718114 100644 --- a/debian/ngcp-rtpengine-daemon.install +++ b/debian/ngcp-rtpengine-daemon.install @@ -1,2 +1,3 @@ daemon/rtpengine /usr/sbin/ recording-daemon/rtpengine-recording /usr/sbin/ +etc/rtpengine.sample.conf /etc/rtpengine/ diff --git a/etc/rtpengine.sample.conf b/etc/rtpengine.sample.conf new file mode 100644 index 000000000..14df93156 --- /dev/null +++ b/etc/rtpengine.sample.conf @@ -0,0 +1,71 @@ +[rtpengine] + +table = 0 +# no-fallback = false +### for userspace forwarding only: +# table = -1 + +### a single interface: +# interface = 123.234.345.456 +### separate multiple interfaces with semicolons: +# interface = internal/12.23.34.45;external/23.34.45.54 +### for different advertised address: +# interface = 12.23.34.45!23.34.45.56 + + + +listen-ng = 127.0.0.1:2223 +# listen-tcp = 25060 +# listen-udp = 12222 + +timeout = 60 +silent-timeout = 3600 +tos = 184 +# delete-delay = 30 +# final-timeout = 10800 + +# foreground = false +# pidfile = /var/run/ngcp-rtpengine-daemon.pid +# num-threads = 16 + +port-min = 30000 +port-max = 50000 +# max-sessions = 5000 + +# recording-dir = /var/spool/rtpengine +# recording-method = proc +# recording-format = raw + +# redis = 127.0.0.1:6379/5 +# redis-write = password@12.23.34.45:6379/42 +# redis-num-threads = 8 +# no-redis-required = false +# redis-expires = 86400 + +# b2b-url = http://127.0.0.1:8090/ +# xmlrpc-format = 0 + +# log-level = 6 +# log-stderr = false +# log-facility = daemon +# log-facility-cdr = local0 +# log-facility-rtcp = local1 + +# graphite = 127.0.0.1:9006 +# graphite-interval = 60 +# graphite-prefix = foobar. + +# homer = 123.234.345.456:65432 +# homer-protocol = udp +# homer-id = 2001 + +# sip-source = false +# dtls-passive = false + +[rtpengine-testing] +table = -1 +interface = 10.15.20.121 +listen-ng = 2223 +foreground = true +log-stderr = true +log-level = 7 diff --git a/lib/auxlib.c b/lib/auxlib.c index 2f20a9167..d75f5d5ad 100644 --- a/lib/auxlib.c +++ b/lib/auxlib.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "loglib.h" void daemonize(void) { @@ -26,3 +28,76 @@ void wpidfile(const char *pidfile) { fclose(fp); } } + +#define CONF_OPTION_GLUE(get_func, data_type, ...) \ + { \ + data_type *varptr = e->arg_data; \ + data_type var = g_key_file_get_ ## get_func(kf, *section_ptr, e->long_name, \ + ##__VA_ARGS__, &er); \ + if (er && g_error_matches(er, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { \ + g_error_free(er); \ + er = NULL; \ + break; \ + } \ + if (er) \ + return er->message; \ + *varptr = var; \ + break; \ + } + +const char *config_load(int *argc, char ***argv, GOptionEntry *entries, const char *description, + char **filename_ptr, const char *default_config, char **section_ptr) +{ + GOptionContext *c; + GError *er = NULL; + const char *config_file; + int fatal = 0; + int saved_argc = *argc; + char **saved_argv = g_strdupv(*argv); + + c = g_option_context_new(description); + g_option_context_add_main_entries(c, entries, NULL); + if (!g_option_context_parse(c, argc, argv, &er)) + return er->message; + + // is there a config file to load? + config_file = default_config; + if (filename_ptr && *filename_ptr) { + config_file = *filename_ptr; + fatal = 1; + } + + GKeyFile *kf = g_key_file_new(); + if (!g_key_file_load_from_file(kf, config_file, G_KEY_FILE_NONE, &er)) { + if (!fatal && (g_error_matches(er, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND) + || g_error_matches(er, G_FILE_ERROR, G_FILE_ERROR_NOENT))) + return NULL; + return er->message; + } + + // iterate the options list and see if the config file defines any + for (GOptionEntry *e = entries; e->long_name; e++) { + switch (e->arg) { + case G_OPTION_ARG_NONE: + CONF_OPTION_GLUE(boolean, int); + + case G_OPTION_ARG_INT: + CONF_OPTION_GLUE(integer, int); + + case G_OPTION_ARG_STRING: + case G_OPTION_ARG_FILENAME: + CONF_OPTION_GLUE(string, char *); + + case G_OPTION_ARG_STRING_ARRAY: + CONF_OPTION_GLUE(string_list, char **, NULL); + + default: + abort(); + } + } + + // process CLI arguments again so they override options from the config file + g_option_context_parse(c, &saved_argc, &saved_argv, &er); + + return NULL; +} diff --git a/lib/auxlib.h b/lib/auxlib.h index 823565a09..0c59cd5e8 100644 --- a/lib/auxlib.h +++ b/lib/auxlib.h @@ -1,9 +1,12 @@ #ifndef _AUXLIB_H_ #define _AUXLIB_H_ +#include void daemonize(void); void wpidfile(const char *pidfile); +const char *config_load(int *argc, char ***argv, GOptionEntry *entries, const char *description, + char **filename_ptr, const char *default_config, char **section_ptr); #endif