diff --git a/README.md b/README.md index 3488787d0..3c6fd7f70 100644 --- a/README.md +++ b/README.md @@ -192,6 +192,7 @@ option and which are reproduced below: -o, --timeout=SECS RTP timeout -s, --silent-timeout=SECS RTP timeout for muted -a, --final-timeout=SECS Call timeout + --offer-timeout=SECS Timeout for incomplete one-sided calls -p, --pidfile=FILE Write PID to file -f, --foreground Don't fork to background -m, --port-min=INT Lowest port to use for RTP @@ -335,6 +336,11 @@ The options are described in more detail below. The number of seconds since call creation, after call is deleted. Useful for limiting the lifetime of a call. This feature can be disabled by setting the parameter to 0. By default this timeout is disabled. +* --offer-timeout + + This timeout (in seconds) is applied to calls which only had an `offer` but no `answer`. + Defaults to 3600 (one hour). + * -p, --pidfile Specifies a path and file name to write the daemon's PID number to. diff --git a/daemon/call.c b/daemon/call.c index 03a084c41..cd5dc86b3 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -249,10 +249,14 @@ no_sfd: check = rtpe_config.timeout; tmp_t_reason = TIMEOUT; - if (!MEDIA_ISSET(ps->media, RECV) || !sfd || !PS_ISSET(ps, FILLED)) { + if (!MEDIA_ISSET(ps->media, RECV) || !sfd) { check = rtpe_config.silent_timeout; tmp_t_reason = SILENT_TIMEOUT; } + else if (!PS_ISSET(ps, FILLED)) { + check = rtpe_config.offer_timeout; + tmp_t_reason = OFFER_TIMEOUT; + } if (rtpe_now.tv_sec - atomic64_get(timestamp) < check) good = 1; diff --git a/daemon/call.h b/daemon/call.h index 778928a0a..4623f6cd4 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -29,7 +29,8 @@ enum termination_reason { FORCED=2, TIMEOUT=3, SILENT_TIMEOUT=4, - FINAL_TIMEOUT=5 + FINAL_TIMEOUT=5, + OFFER_TIMEOUT=6, }; enum tag_type { diff --git a/daemon/cdr.c b/daemon/cdr.c index 0d98e8f94..be1314569 100644 --- a/daemon/cdr.c +++ b/daemon/cdr.c @@ -13,6 +13,7 @@ static const char * const __term_reason_texts[] = { [FORCED] = "FORCED", [SILENT_TIMEOUT] = "SILENT_TIMEOUT", [FINAL_TIMEOUT] = "FINAL_TIMEOUT", + [OFFER_TIMEOUT] = "OFFER_TIMEOUT", }; static const char * const __tag_type_texts[] = { [FROM_TAG] = "FROM_TAG", diff --git a/daemon/cli.c b/daemon/cli.c index a7f7f0480..849ac1f7d 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -46,6 +46,7 @@ static void cli_incoming_set_maxopenfiles(str *instr, struct streambuf *replybuf static void cli_incoming_set_maxsessions(str *instr, struct streambuf *replybuffer); static void cli_incoming_set_timeout(str *instr, struct streambuf *replybuffer); static void cli_incoming_set_silenttimeout(str *instr, struct streambuf *replybuffer); +static void cli_incoming_set_offertimeout(str *instr, struct streambuf *replybuffer); static void cli_incoming_set_finaltimeout(str *instr, struct streambuf *replybuffer); static void cli_incoming_set_loglevel(str *instr, struct streambuf *replybuffer); static void cli_incoming_set_redisallowederrors(str *instr, struct streambuf *replybuffer); @@ -65,6 +66,7 @@ static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer); static void cli_incoming_list_sessions(str *instr, struct streambuf *replybuffer); static void cli_incoming_list_timeout(str *instr, struct streambuf *replybuffer); static void cli_incoming_list_silenttimeout(str *instr, struct streambuf *replybuffer); +static void cli_incoming_list_offertimeout(str *instr, struct streambuf *replybuffer); static void cli_incoming_list_finaltimeout(str *instr, struct streambuf *replybuffer); static void cli_incoming_list_loglevel(str *instr, struct streambuf *replybuffer); static void cli_incoming_list_loglevel(str *instr, struct streambuf *replybuffer); @@ -90,6 +92,7 @@ static const cli_handler_t cli_set_handlers[] = { { "maxsessions", cli_incoming_set_maxsessions }, { "timeout", cli_incoming_set_timeout }, { "silenttimeout", cli_incoming_set_silenttimeout }, + { "offertimeout", cli_incoming_set_offertimeout }, { "finaltimeout", cli_incoming_set_finaltimeout }, { "loglevel", cli_incoming_set_loglevel }, { "redisallowederrors", cli_incoming_set_redisallowederrors }, @@ -107,6 +110,7 @@ static const cli_handler_t cli_list_handlers[] = { { "maxsessions", cli_incoming_list_maxsessions }, { "timeout", cli_incoming_list_timeout }, { "silenttimeout", cli_incoming_list_silenttimeout }, + { "offertimeout", cli_incoming_list_offertimeout }, { "finaltimeout", cli_incoming_list_finaltimeout }, { "loglevel", cli_incoming_list_loglevel }, { "redisallowederrors", cli_incoming_list_redisallowederrors }, @@ -211,12 +215,14 @@ static void cli_incoming_params_start(str *instr, struct streambuf *replybuffer) struct intf_config *ifa; streambuf_printf(replybuffer, "table = %d\nmax-sessions = %d\ntimeout = %d\nsilent-timeout = %d\nfinal-timeout = %d\n" + "offer-timeout = %d\n" "delete-delay = %d\nredis-expires = %d\ntos = %d\ncontrol-tos = %d\ngraphite-interval = %d\nredis-num-threads = %d\n" "homer-protocol = %d\nhomer-id = %d\nno-fallback = %d\nport-min = %d\nport-max = %d\nredis = %s:%d/%d\n" "redis-write = %s:%d/%d\nno-redis-required = %d\nnum-threads = %d\nxmlrpc-format = %d\nlog_format = %d\n" "redis_allowed_errors = %d\nredis_disable_time = %d\nredis_cmd_timeout = %d\nredis_connect_timeout = %d\n", initial_rtpe_config.kernel_table, initial_rtpe_config.max_sessions, initial_rtpe_config.timeout, - initial_rtpe_config.silent_timeout, initial_rtpe_config.final_timeout, initial_rtpe_config.delete_delay, + initial_rtpe_config.silent_timeout, initial_rtpe_config.final_timeout, initial_rtpe_config.offer_timeout, + initial_rtpe_config.delete_delay, initial_rtpe_config.redis_expires_secs, initial_rtpe_config.default_tos, initial_rtpe_config.control_tos, initial_rtpe_config.graphite_interval, initial_rtpe_config.redis_num_threads, initial_rtpe_config.homer_protocol, initial_rtpe_config.homer_id, initial_rtpe_config.no_fallback, initial_rtpe_config.port_min, initial_rtpe_config.port_max, @@ -253,12 +259,15 @@ static void cli_incoming_params_current(str *instr, struct streambuf *replybuffe struct intf_config *ifa; streambuf_printf(replybuffer, "table = %d\nmax-sessions = %d\ntimeout = %d\nsilent-timeout = %d\nfinal-timeout = %d\n" + "offer-timeout = %d\n" "delete-delay = %d\nredis-expires = %d\ntos = %d\ncontrol-tos = %d\ngraphite-interval = %d\nredis-num-threads = %d\n" "homer-protocol = %d\nhomer-id = %d\nno-fallback = %d\nport-min = %d\nport-max = %d\nredis-db = %d\n" "redis-write-db = %d\nno-redis-required = %d\nnum-threads = %d\nxmlrpc-format = %d\nlog_format = %d\n" "redis_allowed_errors = %d\nredis_disable_time = %d\nredis_cmd_timeout = %d\nredis_connect_timeout = %d\n", rtpe_config.kernel_table, rtpe_config.max_sessions, rtpe_config.timeout, rtpe_config.silent_timeout, - rtpe_config.final_timeout, rtpe_config.delete_delay, rtpe_config.redis_expires_secs, rtpe_config.default_tos, + rtpe_config.final_timeout, + rtpe_config.offer_timeout, + rtpe_config.delete_delay, rtpe_config.redis_expires_secs, rtpe_config.default_tos, rtpe_config.control_tos, rtpe_config.graphite_interval, rtpe_config.redis_num_threads, rtpe_config.homer_protocol, rtpe_config.homer_id, rtpe_config.no_fallback, rtpe_config.port_min, rtpe_config.port_max, rtpe_config.redis_db, rtpe_config.redis_write_db, rtpe_config.no_redis_required, @@ -314,6 +323,7 @@ static void cli_incoming_params_diff(str *instr, struct streambuf *replybuffer) int_diff_print(initial_rtpe_config.timeout, rtpe_config.timeout, "timeout", replybuffer); int_diff_print(initial_rtpe_config.silent_timeout, rtpe_config.silent_timeout, "silent-timeout", replybuffer); int_diff_print(initial_rtpe_config.final_timeout, rtpe_config.final_timeout, "final-timeout", replybuffer); + int_diff_print(initial_rtpe_config.offer_timeout, rtpe_config.offer_timeout, "offer-timeout", replybuffer); int_diff_print(initial_rtpe_config.delete_delay, rtpe_config.delete_delay, "delete-delay", replybuffer); int_diff_print(initial_rtpe_config.redis_expires_secs, rtpe_config.redis_expires_secs, "redis-expires", replybuffer); int_diff_print(initial_rtpe_config.default_tos, rtpe_config.default_tos, "default-tos", replybuffer); @@ -400,6 +410,7 @@ static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer) streambuf_printf(replybuffer, " Total timed-out sessions via TIMEOUT :"UINT64F"\n",atomic64_get(&rtpe_totalstats.total_timeout_sess)); streambuf_printf(replybuffer, " Total timed-out sessions via SILENT_TIMEOUT :"UINT64F"\n",atomic64_get(&rtpe_totalstats.total_silent_timeout_sess)); streambuf_printf(replybuffer, " Total timed-out sessions via FINAL_TIMEOUT :"UINT64F"\n",atomic64_get(&rtpe_totalstats.total_final_timeout_sess)); + streambuf_printf(replybuffer, " Total timed-out sessions via OFFER_TIMEOUT :"UINT64F"\n",atomic64_get(&rtpe_totalstats.total_offer_timeout_sess)); streambuf_printf(replybuffer, " Total regular terminated sessions :"UINT64F"\n",atomic64_get(&rtpe_totalstats.total_regular_term_sess)); streambuf_printf(replybuffer, " Total forced terminated sessions :"UINT64F"\n",atomic64_get(&rtpe_totalstats.total_forced_term_sess)); streambuf_printf(replybuffer, " Total relayed packets :"UINT64F"\n",atomic64_get(&rtpe_totalstats.total_relayed_packets)); @@ -543,6 +554,16 @@ static void cli_incoming_list_finaltimeout(str *instr, struct streambuf *replybu return ; } +static void cli_incoming_list_offertimeout(str *instr, struct streambuf *replybuffer) { + rwlock_lock_r(&rtpe_config.config_lock); + + /* don't lock anything while reading the value */ + streambuf_printf(replybuffer, "OFFER_TIMEOUT=%u\n", rtpe_config.offer_timeout); + + rwlock_unlock_r(&rtpe_config.config_lock); + + return ; +} static void cli_incoming_list_callid(str *instr, struct streambuf *replybuffer) { struct call* c=0; @@ -818,6 +839,9 @@ static void cli_incoming_set_silenttimeout(str *instr, struct streambuf *replybu static void cli_incoming_set_finaltimeout(str *instr, struct streambuf *replybuffer) { cli_incoming_set_gentimeout(instr, replybuffer, &rtpe_config.final_timeout); } +static void cli_incoming_set_offertimeout(str *instr, struct streambuf *replybuffer) { + cli_incoming_set_gentimeout(instr, replybuffer, &rtpe_config.offer_timeout); +} static void cli_incoming_list(str *instr, struct streambuf *replybuffer) { if (str_shift(instr, 1)) { diff --git a/daemon/graphite.c b/daemon/graphite.c index c10845fed..1a4bea7c5 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -116,6 +116,7 @@ int send_graphite_data(struct totalstats *sent_data) { atomic64_local_copy_zero_struct(ts, &rtpe_totalstats_interval, total_rejected_sess); atomic64_local_copy_zero_struct(ts, &rtpe_totalstats_interval, total_silent_timeout_sess); atomic64_local_copy_zero_struct(ts, &rtpe_totalstats_interval, total_final_timeout_sess); + atomic64_local_copy_zero_struct(ts, &rtpe_totalstats_interval, total_offer_timeout_sess); atomic64_local_copy_zero_struct(ts, &rtpe_totalstats_interval, total_regular_term_sess); atomic64_local_copy_zero_struct(ts, &rtpe_totalstats_interval, total_forced_term_sess); atomic64_local_copy_zero_struct(ts, &rtpe_totalstats_interval, total_relayed_packets); @@ -220,6 +221,8 @@ int send_graphite_data(struct totalstats *sent_data) { if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"final_timeout_sess "UINT64F" %llu\n", atomic64_get_na(&ts->total_final_timeout_sess),(unsigned long long)rtpe_now.tv_sec); ptr += rc; if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"offer_timeout_sess "UINT64F" %llu\n", atomic64_get_na(&ts->total_offer_timeout_sess),(unsigned long long)rtpe_now.tv_sec); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"timeout_sess "UINT64F" %llu\n", atomic64_get_na(&ts->total_timeout_sess),(unsigned long long)rtpe_now.tv_sec); ptr += rc; if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"reject_sess "UINT64F" %llu\n", atomic64_get_na(&ts->total_rejected_sess),(unsigned long long)rtpe_now.tv_sec); ptr += rc; diff --git a/daemon/main.c b/daemon/main.c index 94ba33b41..3ee68dfa1 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -263,6 +263,7 @@ static void options(int *argc, char ***argv) { { "timeout", 'o', 0, G_OPTION_ARG_INT, &rtpe_config.timeout, "RTP timeout", "SECS" }, { "silent-timeout",'s',0,G_OPTION_ARG_INT, &rtpe_config.silent_timeout,"RTP timeout for muted", "SECS" }, { "final-timeout",'a',0,G_OPTION_ARG_INT, &rtpe_config.final_timeout, "Call timeout", "SECS" }, + { "offer-timeout",0,0, G_OPTION_ARG_INT, &rtpe_config.offer_timeout, "Timeout for incomplete one-sided calls", "SECS" }, { "port-min", 'm', 0, G_OPTION_ARG_INT, &rtpe_config.port_min, "Lowest port to use for RTP", "INT" }, { "port-max", 'M', 0, G_OPTION_ARG_INT, &rtpe_config.port_max, "Highest port to use for RTP", "INT" }, { "redis", 'r', 0, G_OPTION_ARG_STRING, &redisps, "Connect to Redis database", "[PW@]IP:PORT/INT" }, @@ -383,6 +384,9 @@ static void options(int *argc, char ***argv) { if (rtpe_config.silent_timeout <= 0) rtpe_config.silent_timeout = 3600; + if (rtpe_config.offer_timeout <= 0) + rtpe_config.offer_timeout = 3600; + if (rtpe_config.final_timeout <= 0) rtpe_config.final_timeout = 0; @@ -447,6 +451,7 @@ void fill_initial_rtpe_cfg(struct rtpengine_config* ini_rtpe_cfg) { ini_rtpe_cfg->max_sessions = rtpe_config.max_sessions; ini_rtpe_cfg->timeout = rtpe_config.timeout; ini_rtpe_cfg->silent_timeout = rtpe_config.silent_timeout; + ini_rtpe_cfg->offer_timeout = rtpe_config.offer_timeout; ini_rtpe_cfg->final_timeout = rtpe_config.final_timeout; ini_rtpe_cfg->delete_delay = rtpe_config.delete_delay; ini_rtpe_cfg->redis_expires_secs = rtpe_config.redis_expires_secs; diff --git a/daemon/main.h b/daemon/main.h index 50e2f3c89..5f7089f07 100644 --- a/daemon/main.h +++ b/daemon/main.h @@ -29,6 +29,7 @@ struct rtpengine_config { int timeout; int silent_timeout; int final_timeout; + int offer_timeout; int delete_delay; GQueue redis_subscribed_keyspaces; int redis_expires_secs; diff --git a/daemon/statistics.c b/daemon/statistics.c index df7909531..8a3745fda 100644 --- a/daemon/statistics.c +++ b/daemon/statistics.c @@ -191,6 +191,9 @@ void statistics_update_oneway(struct call* c) { } else if (ml->term_reason==SILENT_TIMEOUT) { atomic64_inc(&rtpe_totalstats.total_silent_timeout_sess); atomic64_inc(&rtpe_totalstats_interval.total_silent_timeout_sess); + } else if (ml->term_reason==OFFER_TIMEOUT) { + atomic64_inc(&rtpe_totalstats.total_offer_timeout_sess); + atomic64_inc(&rtpe_totalstats_interval.total_offer_timeout_sess); } else if (ml->term_reason==REGULAR) { atomic64_inc(&rtpe_totalstats.total_regular_term_sess); atomic64_inc(&rtpe_totalstats_interval.total_regular_term_sess); diff --git a/daemon/statistics.h b/daemon/statistics.h index 01c4bfb69..3e25022c2 100644 --- a/daemon/statistics.h +++ b/daemon/statistics.h @@ -39,6 +39,7 @@ struct totalstats { atomic64 total_foreign_sessions; atomic64 total_rejected_sess; atomic64 total_silent_timeout_sess; + atomic64 total_offer_timeout_sess; atomic64 total_final_timeout_sess; atomic64 total_regular_term_sess; atomic64 total_forced_term_sess;