Merge remote-tracking branch 'upstream/master'

pull/225/head
Stefan Mititelu 9 years ago
commit d7a75a1256

@ -164,6 +164,7 @@ option and which are reproduced below:
-T, --tos=INT TOS value to set on streams -T, --tos=INT TOS value to set on streams
-o, --timeout=SECS RTP timeout -o, --timeout=SECS RTP timeout
-s, --silent-timeout=SECS RTP timeout for muted -s, --silent-timeout=SECS RTP timeout for muted
-a, --final-timeout=SECS Call timeout
-p, --pidfile=FILE Write PID to file -p, --pidfile=FILE Write PID to file
-f, --foreground Don't fork to background -f, --foreground Don't fork to background
-m, --port-min=INT Lowest port to use for RTP -m, --port-min=INT Lowest port to use for RTP
@ -293,6 +294,11 @@ The options are described in more detail below.
Ditto as the `--timeout` option, but applies to muted or inactive media streams. Defaults to 3600 Ditto as the `--timeout` option, but applies to muted or inactive media streams. Defaults to 3600
(one hour). (one hour).
* -a, --final-timeout
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.
* -p, --pidfile * -p, --pidfile
Specifies a path and file name to write the daemon's PID number to. Specifies a path and file name to write the daemon's PID number to.
@ -718,6 +724,10 @@ Optionally included keys are:
Corresponds to the *rtpproxy* `a` flag. Advertises an RTP endpoint which uses asymmetric Corresponds to the *rtpproxy* `a` flag. Advertises an RTP endpoint which uses asymmetric
RTP, which disables learning of endpoint addresses (see below). RTP, which disables learning of endpoint addresses (see below).
- `unidirectional`
When this flag is present, kernelize also one-way rtp media.
- `strict source` - `strict source`
Normally, *rtpengine* attempts to learn the correct endpoint address for every stream during Normally, *rtpengine* attempts to learn the correct endpoint address for every stream during

@ -569,6 +569,11 @@ INLINE void timeval_multiply(struct timeval *result, const struct timeval *a, co
timeval_from_us(result, timeval_us(a) * multiplier); timeval_from_us(result, timeval_us(a) * multiplier);
} }
INLINE void timeval_divide(struct timeval *result, const struct timeval *a, const long divisor) { INLINE void timeval_divide(struct timeval *result, const struct timeval *a, const long divisor) {
if (divisor == 0) {
result->tv_sec = 0;
result->tv_usec = 0;
return ;
}
timeval_from_us(result, timeval_us(a) / divisor); timeval_from_us(result, timeval_us(a) / divisor);
} }
INLINE void timeval_add(struct timeval *result, const struct timeval *a, const struct timeval *b) { INLINE void timeval_add(struct timeval *result, const struct timeval *a, const struct timeval *b) {

@ -108,6 +108,7 @@ static const char * const __term_reason_texts[] = {
[REGULAR] = "REGULAR", [REGULAR] = "REGULAR",
[FORCED] = "FORCED", [FORCED] = "FORCED",
[SILENT_TIMEOUT] = "SILENT_TIMEOUT", [SILENT_TIMEOUT] = "SILENT_TIMEOUT",
[FINAL_TIMEOUT] = "FINAL_TIMEOUT",
}; };
static const char * const __tag_type_texts[] = { static const char * const __tag_type_texts[] = {
[FROM_TAG] = "FROM_TAG", [FROM_TAG] = "FROM_TAG",
@ -179,7 +180,7 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
int good = 0; int good = 0;
struct packet_stream *ps; struct packet_stream *ps;
struct stream_fd *sfd; struct stream_fd *sfd;
int tmp_t_reason=0; int tmp_t_reason = UNKNOWN;
struct call_monologue *ml; struct call_monologue *ml;
enum call_stream_state css; enum call_stream_state css;
atomic64 *timestamp; atomic64 *timestamp;
@ -188,6 +189,19 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
log_info_call(c); log_info_call(c);
cm = c->callmaster; cm = c->callmaster;
rwlock_lock_r(&cm->conf.config_lock);
if (cm->conf.final_timeout && poller_now >= (c->created + cm->conf.final_timeout)) {
ilog(LOG_INFO, "Closing call due to final timeout");
tmp_t_reason = FINAL_TIMEOUT;
for (it = c->monologues.head; it; it = it->next) {
ml = it->data;
gettimeofday(&(ml->terminated),NULL);
ml->term_reason = tmp_t_reason;
}
goto delete;
}
if (c->redis_foreign_call) { if (c->redis_foreign_call) {
ilog(LOG_DEBUG, "Redis-Notification: Timeout resets the deletion timers for a call where I am not responsible."); ilog(LOG_DEBUG, "Redis-Notification: Timeout resets the deletion timers for a call where I am not responsible.");
@ -234,10 +248,10 @@ no_sfd:
goto next; goto next;
check = cm->conf.timeout; check = cm->conf.timeout;
tmp_t_reason = 1; tmp_t_reason = TIMEOUT;
if (!MEDIA_ISSET(ps->media, RECV) || !sfd || !PS_ISSET(ps, FILLED)) { if (!MEDIA_ISSET(ps->media, RECV) || !sfd || !PS_ISSET(ps, FILLED)) {
check = cm->conf.silent_timeout; check = cm->conf.silent_timeout;
tmp_t_reason = 2; tmp_t_reason = SILENT_TIMEOUT;
} }
if (poller_now - atomic64_get(timestamp) < check) if (poller_now - atomic64_get(timestamp) < check)
@ -257,13 +271,7 @@ next:
for (it = c->monologues.head; it; it = it->next) { for (it = c->monologues.head; it; it = it->next) {
ml = it->data; ml = it->data;
gettimeofday(&(ml->terminated),NULL); gettimeofday(&(ml->terminated),NULL);
if (tmp_t_reason==1) { ml->term_reason = tmp_t_reason;
ml->term_reason = TIMEOUT;
} else if (tmp_t_reason==2) {
ml->term_reason = SILENT_TIMEOUT;
} else {
ml->term_reason = UNKNOWN;
}
} }
ilog(LOG_INFO, "Closing call due to timeout"); ilog(LOG_INFO, "Closing call due to timeout");
@ -277,6 +285,7 @@ delete:
goto out; goto out;
out: out:
rwlock_unlock_r(&cm->conf.config_lock);
rwlock_unlock_r(&c->master_lock); rwlock_unlock_r(&c->master_lock);
log_info_clear(); log_info_clear();
} }
@ -1561,8 +1570,8 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams,
if (sp->rtp_endpoint.port) { if (sp->rtp_endpoint.port) {
/* copy parameters advertised by the sender of this message */ /* copy parameters advertised by the sender of this message */
bf_copy_same(&other_media->media_flags, &sp->sp_flags, bf_copy_same(&other_media->media_flags, &sp->sp_flags,
SHARED_FLAG_RTCP_MUX | SHARED_FLAG_ASYMMETRIC | SHARED_FLAG_ICE SHARED_FLAG_RTCP_MUX | SHARED_FLAG_ASYMMETRIC | SHARED_FLAG_UNIDIRECTIONAL |
| SHARED_FLAG_TRICKLE_ICE | SHARED_FLAG_ICE_LITE); SHARED_FLAG_ICE | SHARED_FLAG_TRICKLE_ICE | SHARED_FLAG_ICE_LITE);
crypto_params_copy(&other_media->sdes_in.params, &sp->crypto, 1); crypto_params_copy(&other_media->sdes_in.params, &sp->crypto, 1);
other_media->sdes_in.tag = sp->sdes_tag; other_media->sdes_in.tag = sp->sdes_tag;
@ -2168,6 +2177,11 @@ void call_destroy(struct call *c) {
&m->latest_graphite_interval_start, &m->latest_graphite_interval_start,
m->conf.graphite_interval); m->conf.graphite_interval);
} }
if (ml->term_reason==FINAL_TIMEOUT) {
atomic64_inc(&m->totalstats.total_final_timeout_sess);
atomic64_inc(&m->totalstats_interval.total_final_timeout_sess);
}
} }

@ -35,7 +35,8 @@ enum termination_reason {
REGULAR=1, REGULAR=1,
FORCED=2, FORCED=2,
TIMEOUT=3, TIMEOUT=3,
SILENT_TIMEOUT=4 SILENT_TIMEOUT=4,
FINAL_TIMEOUT=5
}; };
enum tag_type { enum tag_type {
@ -128,6 +129,7 @@ enum call_type {
#define SHARED_FLAG_MEDIA_HANDOVER 0x00000200 #define SHARED_FLAG_MEDIA_HANDOVER 0x00000200
#define SHARED_FLAG_TRICKLE_ICE 0x00000400 #define SHARED_FLAG_TRICKLE_ICE 0x00000400
#define SHARED_FLAG_ICE_LITE 0x00000800 #define SHARED_FLAG_ICE_LITE 0x00000800
#define SHARED_FLAG_UNIDIRECTIONAL 0x00001000
/* struct stream_params */ /* struct stream_params */
#define SP_FLAG_NO_RTCP 0x00010000 #define SP_FLAG_NO_RTCP 0x00010000
@ -136,6 +138,7 @@ enum call_type {
#define SP_FLAG_SEND SHARED_FLAG_SEND #define SP_FLAG_SEND SHARED_FLAG_SEND
#define SP_FLAG_RECV SHARED_FLAG_RECV #define SP_FLAG_RECV SHARED_FLAG_RECV
#define SP_FLAG_ASYMMETRIC SHARED_FLAG_ASYMMETRIC #define SP_FLAG_ASYMMETRIC SHARED_FLAG_ASYMMETRIC
#define SP_FLAG_UNIDIRECTIONAL SHARED_FLAG_UNIDIRECTIONAL
#define SP_FLAG_SETUP_ACTIVE SHARED_FLAG_SETUP_ACTIVE #define SP_FLAG_SETUP_ACTIVE SHARED_FLAG_SETUP_ACTIVE
#define SP_FLAG_SETUP_PASSIVE SHARED_FLAG_SETUP_PASSIVE #define SP_FLAG_SETUP_PASSIVE SHARED_FLAG_SETUP_PASSIVE
#define SP_FLAG_ICE SHARED_FLAG_ICE #define SP_FLAG_ICE SHARED_FLAG_ICE
@ -163,6 +166,7 @@ enum call_type {
/* struct call_media */ /* struct call_media */
#define MEDIA_FLAG_INITIALIZED 0x00010000 #define MEDIA_FLAG_INITIALIZED 0x00010000
#define MEDIA_FLAG_ASYMMETRIC SHARED_FLAG_ASYMMETRIC #define MEDIA_FLAG_ASYMMETRIC SHARED_FLAG_ASYMMETRIC
#define MEDIA_FLAG_UNIDIRECTIONAL SHARED_FLAG_UNIDIRECTIONAL
#define MEDIA_FLAG_SEND SHARED_FLAG_SEND #define MEDIA_FLAG_SEND SHARED_FLAG_SEND
#define MEDIA_FLAG_RECV SHARED_FLAG_RECV #define MEDIA_FLAG_RECV SHARED_FLAG_RECV
#define MEDIA_FLAG_RTCP_MUX SHARED_FLAG_RTCP_MUX #define MEDIA_FLAG_RTCP_MUX SHARED_FLAG_RTCP_MUX
@ -236,12 +240,19 @@ struct stats {
atomic64 foreign_sessions; // unresponsible via redis notification atomic64 foreign_sessions; // unresponsible via redis notification
}; };
struct request_time {
mutex_t lock;
u_int64_t count;
struct timeval time_min, time_max, time_avg;
};
struct totalstats { struct totalstats {
time_t started; time_t started;
atomic64 total_timeout_sess; atomic64 total_timeout_sess;
atomic64 total_foreign_sessions; atomic64 total_foreign_sessions;
atomic64 total_rejected_sess; atomic64 total_rejected_sess;
atomic64 total_silent_timeout_sess; atomic64 total_silent_timeout_sess;
atomic64 total_final_timeout_sess;
atomic64 total_regular_term_sess; atomic64 total_regular_term_sess;
atomic64 total_forced_term_sess; atomic64 total_forced_term_sess;
atomic64 total_relayed_packets; atomic64 total_relayed_packets;
@ -259,6 +270,8 @@ struct totalstats {
mutex_t total_calls_duration_lock; /* for these two below */ mutex_t total_calls_duration_lock; /* for these two below */
struct timeval total_calls_duration_interval; struct timeval total_calls_duration_interval;
struct request_time offer, answer, delete;
}; };
struct stream_params { struct stream_params {
@ -428,9 +441,14 @@ struct call {
struct callmaster_config { struct callmaster_config {
int kernelfd; int kernelfd;
int kernelid; int kernelid;
/* everything below protected by config_lock */
rwlock_t config_lock;
int max_sessions; int max_sessions;
unsigned int timeout; unsigned int timeout;
unsigned int silent_timeout; unsigned int silent_timeout;
unsigned int final_timeout;
unsigned int delete_delay; unsigned int delete_delay;
struct redis *redis; struct redis *redis;
struct redis *redis_write; struct redis *redis_write;

@ -388,10 +388,12 @@ str *call_query_udp(char **out, struct callmaster *m) {
rwlock_unlock_w(&c->master_lock); rwlock_unlock_w(&c->master_lock);
rwlock_lock_r(&m->conf.config_lock);
ret = str_sprintf("%s %lld "UINT64F" "UINT64F" "UINT64F" "UINT64F"\n", out[RE_UDP_COOKIE], ret = str_sprintf("%s %lld "UINT64F" "UINT64F" "UINT64F" "UINT64F"\n", out[RE_UDP_COOKIE],
(long long int) m->conf.silent_timeout - (poller_now - stats.last_packet), (long long int) m->conf.silent_timeout - (poller_now - stats.last_packet),
atomic64_get_na(&stats.totals[0].packets), atomic64_get_na(&stats.totals[1].packets), atomic64_get_na(&stats.totals[0].packets), atomic64_get_na(&stats.totals[1].packets),
atomic64_get_na(&stats.totals[2].packets), atomic64_get_na(&stats.totals[3].packets)); atomic64_get_na(&stats.totals[2].packets), atomic64_get_na(&stats.totals[3].packets));
rwlock_unlock_r(&m->conf.config_lock);
goto out; goto out;
err: err:
@ -541,6 +543,8 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu
out->trust_address = 0; out->trust_address = 0;
else if (!bencode_strcmp(it, "asymmetric")) else if (!bencode_strcmp(it, "asymmetric"))
out->asymmetric = 1; out->asymmetric = 1;
else if (!bencode_strcmp(it, "unidirectional"))
out->unidirectional = 1;
else if (!bencode_strcmp(it, "strict-source")) else if (!bencode_strcmp(it, "strict-source"))
out->strict_source = 1; out->strict_source = 1;
else if (!bencode_strcmp(it, "media-handover")) else if (!bencode_strcmp(it, "media-handover"))
@ -741,6 +745,7 @@ out:
const char *call_offer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output, const char* addr, const char *call_offer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output, const char* addr,
const endpoint_t *sin) const endpoint_t *sin)
{ {
rwlock_lock_r(&m->conf.config_lock);
if (m->conf.max_sessions>=0) { if (m->conf.max_sessions>=0) {
rwlock_lock_r(&m->hashlock); rwlock_lock_r(&m->hashlock);
if (g_hash_table_size(m->callhash) - if (g_hash_table_size(m->callhash) -
@ -751,10 +756,14 @@ const char *call_offer_ng(bencode_item_t *input, struct callmaster *m, bencode_i
atomic64_inc(&m->totalstats.total_rejected_sess); atomic64_inc(&m->totalstats.total_rejected_sess);
atomic64_inc(&m->totalstats_interval.total_rejected_sess); atomic64_inc(&m->totalstats_interval.total_rejected_sess);
ilog(LOG_ERROR, "Parallel session limit reached (%i)",m->conf.max_sessions); ilog(LOG_ERROR, "Parallel session limit reached (%i)",m->conf.max_sessions);
rwlock_unlock_r(&m->conf.config_lock);
return "Parallel session limit reached"; return "Parallel session limit reached";
} }
rwlock_unlock_r(&m->hashlock); rwlock_unlock_r(&m->hashlock);
} }
rwlock_unlock_r(&m->conf.config_lock);
return call_offer_answer_ng(input, m, output, OP_OFFER, addr, sin); return call_offer_answer_ng(input, m, output, OP_OFFER, addr, sin);
} }

@ -31,6 +31,7 @@ struct sdp_ng_flags {
sockfamily_t *address_family; sockfamily_t *address_family;
int tos; int tos;
int asymmetric:1, int asymmetric:1,
unidirectional:1,
trust_address:1, trust_address:1,
port_latching:1, port_latching:1,
replace_origin:1, replace_origin:1,

@ -22,6 +22,7 @@ static void cli_incoming_list_totals(char* buffer, int len, struct callmaster* m
int printlen=0; int printlen=0;
struct timeval avg, calls_dur_iv; struct timeval avg, calls_dur_iv;
u_int64_t num_sessions, min_sess_iv, max_sess_iv; u_int64_t num_sessions, min_sess_iv, max_sess_iv;
struct request_time offer_iv, answer_iv, delete_iv;
mutex_lock(&m->totalstats.total_average_lock); mutex_lock(&m->totalstats.total_average_lock);
avg = m->totalstats.total_average_call_dur; avg = m->totalstats.total_average_call_dur;
@ -40,6 +41,8 @@ static void cli_incoming_list_totals(char* buffer, int len, struct callmaster* m
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total timed-out sessions via SILENT_TIMEOUT :"UINT64F"\n",atomic64_get(&m->totalstats.total_silent_timeout_sess)); printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total timed-out sessions via SILENT_TIMEOUT :"UINT64F"\n",atomic64_get(&m->totalstats.total_silent_timeout_sess));
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total timed-out sessions via FINAL_TIMEOUT :"UINT64F"\n",atomic64_get(&m->totalstats.total_final_timeout_sess));
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total regular terminated sessions :"UINT64F"\n",atomic64_get(&m->totalstats.total_regular_term_sess)); printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total regular terminated sessions :"UINT64F"\n",atomic64_get(&m->totalstats.total_regular_term_sess));
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total forced terminated sessions :"UINT64F"\n",atomic64_get(&m->totalstats.total_forced_term_sess)); printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total forced terminated sessions :"UINT64F"\n",atomic64_get(&m->totalstats.total_forced_term_sess));
@ -59,7 +62,15 @@ static void cli_incoming_list_totals(char* buffer, int len, struct callmaster* m
calls_dur_iv = m->totalstats_lastinterval.total_calls_duration_interval; calls_dur_iv = m->totalstats_lastinterval.total_calls_duration_interval;
min_sess_iv = m->totalstats_lastinterval.managed_sess_min; min_sess_iv = m->totalstats_lastinterval.managed_sess_min;
max_sess_iv = m->totalstats_lastinterval.managed_sess_max; max_sess_iv = m->totalstats_lastinterval.managed_sess_max;
mutex_unlock(&m->totalstats_lastinterval_lock); offer_iv = m->totalstats_lastinterval.offer;
answer_iv = m->totalstats_lastinterval.answer;
delete_iv = m->totalstats_lastinterval.delete;
mutex_unlock(&m->totalstats_lastinterval_lock);
// compute average offer/answer/delete time
timeval_divide(&offer_iv.time_avg, &offer_iv.time_avg, offer_iv.count);
timeval_divide(&answer_iv.time_avg, &answer_iv.time_avg, answer_iv.count);
timeval_divide(&delete_iv.time_avg, &delete_iv.time_avg, delete_iv.count);
printlen = snprintf(replybuffer,(outbufend-replybuffer), "\nGraphite interval statistics (last reported values to graphite):\n"); printlen = snprintf(replybuffer,(outbufend-replybuffer), "\nGraphite interval statistics (last reported values to graphite):\n");
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
@ -69,6 +80,21 @@ static void cli_incoming_list_totals(char* buffer, int len, struct callmaster* m
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Max managed sessions :"UINT64F"\n", max_sess_iv); printlen = snprintf(replybuffer,(outbufend-replybuffer), " Max managed sessions :"UINT64F"\n", max_sess_iv);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Min/Max/Avg offer processing delay :%llu.%06llu/%llu.%06llu/%llu.%06llu sec\n",
(unsigned long long)offer_iv.time_min.tv_sec,(unsigned long long)offer_iv.time_min.tv_usec,
(unsigned long long)offer_iv.time_max.tv_sec,(unsigned long long)offer_iv.time_max.tv_usec,
(unsigned long long)offer_iv.time_avg.tv_sec,(unsigned long long)offer_iv.time_avg.tv_usec);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Min/Max/Avg answer processing delay :%llu.%06llu/%llu.%06llu/%llu.%06llu sec\n",
(unsigned long long)answer_iv.time_min.tv_sec,(unsigned long long)answer_iv.time_min.tv_usec,
(unsigned long long)answer_iv.time_max.tv_sec,(unsigned long long)answer_iv.time_max.tv_usec,
(unsigned long long)answer_iv.time_avg.tv_sec,(unsigned long long)answer_iv.time_avg.tv_usec);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Min/Max/Avg delete processing delay :%llu.%06llu/%llu.%06llu/%llu.%06llu sec\n",
(unsigned long long)delete_iv.time_min.tv_sec,(unsigned long long)delete_iv.time_min.tv_usec,
(unsigned long long)delete_iv.time_max.tv_sec,(unsigned long long)delete_iv.time_max.tv_usec,
(unsigned long long)delete_iv.time_avg.tv_sec,(unsigned long long)delete_iv.time_avg.tv_usec);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), "\n\n"); printlen = snprintf(replybuffer,(outbufend-replybuffer), "\n\n");
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
@ -137,6 +163,24 @@ static void cli_incoming_list_maxopenfiles(char* buffer, int len, struct callmas
return ; return ;
} }
static void cli_incoming_list_timeout(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
int printlen=0;
rwlock_lock_r(&m->conf.config_lock);
/* don't lock anything while reading the value */
printlen = snprintf(replybuffer,(outbufend-replybuffer), "TIMEOUT=%u\n", m->conf.timeout);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), "SILENT_TIMEOUT=%u\n", m->conf.silent_timeout);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), "FINAL_TIMEOUT=%u\n", m->conf.final_timeout);
ADJUSTLEN(printlen,outbufend,replybuffer);
rwlock_unlock_r(&m->conf.config_lock);
return ;
}
static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
str callid; str callid;
struct call* c=0; struct call* c=0;
@ -250,11 +294,12 @@ static void cli_incoming_set_maxopenfiles(char* buffer, int len, struct callmast
unsigned int open_files_num; unsigned int open_files_num;
str open_files; str open_files;
pid_t pid; pid_t pid;
char *endptr;
// limit the minimum number of open files to avoid rtpengine freeze for low open_files_num values // limit the minimum number of open files to avoid rtpengine freeze for low open_files_num values
unsigned int min_open_files_num = (1 << 16); unsigned int min_open_files_num = (1 << 16);
if (len<=1) { if (len <= 1) {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required."); printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required.");
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
return; return;
@ -263,23 +308,27 @@ static void cli_incoming_set_maxopenfiles(char* buffer, int len, struct callmast
++buffer; --len; // one space ++buffer; --len; // one space
open_files.s = buffer; open_files.s = buffer;
open_files.len = len; open_files.len = len;
open_files_num = str_to_ui(&open_files, -1); open_files_num = strtol(open_files.s, &endptr, 10);
if (open_files_num == -1) { if ((errno == ERANGE && (open_files_num == LONG_MAX || open_files_num == LONG_MIN)) || (errno != 0 && open_files_num == 0)) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; not an unsigned integer\n", open_files.len, open_files.s); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; errno=%d\n", open_files.len, open_files.s, errno);
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
} else if (endptr == open_files.s) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; no digists found\n", open_files.len, open_files.s);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
return; return;
} else if (open_files_num < min_open_files_num) { } else if (open_files_num < min_open_files_num) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; can't set it under %u\n", open_files.len, open_files.s, min_open_files_num); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %u; can't set it under %u\n", open_files_num, min_open_files_num);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
return; return;
} else if (rlim(RLIMIT_NOFILE, open_files_num) == -1){ } else if (rlim(RLIMIT_NOFILE, open_files_num) == -1){
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; errno = %d\n", open_files.len, open_files.s, errno); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %u; errno = %d\n", open_files_num, errno);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
return; return;
} else { } else {
pid = getpid(); pid = getpid();
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting open_files to %.*s; cat /proc/%u/limits\n", open_files.len, open_files.s, pid); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting open_files to %u; cat /proc/%u/limits\n", open_files_num, pid);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
} }
} }
@ -287,11 +336,11 @@ static void cli_incoming_set_maxopenfiles(char* buffer, int len, struct callmast
static void cli_incoming_set_maxsessions(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { static void cli_incoming_set_maxsessions(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
int printlen = 0; int printlen = 0;
int maxsessions_num; int maxsessions_num;
int err = 0x80000000;
int disabled = -1; int disabled = -1;
str maxsessions; str maxsessions;
char *endptr;
if (len<=1) { if (len <= 1) {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required."); printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required.");
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
return; return;
@ -300,22 +349,29 @@ static void cli_incoming_set_maxsessions(char* buffer, int len, struct callmaste
++buffer; --len; // one space ++buffer; --len; // one space
maxsessions.s = buffer; maxsessions.s = buffer;
maxsessions.len = len; maxsessions.len = len;
maxsessions_num = str_to_i(&maxsessions, err); maxsessions_num = strtol(maxsessions.s, &endptr, 10);
if (maxsessions_num == err) { if ((errno == ERANGE && (maxsessions_num == LONG_MAX || maxsessions_num == LONG_MIN)) || (errno != 0 && maxsessions_num == 0)) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting maxsessions to %.*s; not an integer\n", maxsessions.len, maxsessions.s); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting maxsessions to %.*s; errno=%d\n", maxsessions.len, maxsessions.s, errno);
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
} else if (endptr == maxsessions.s) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting maxsessions to %.*s; no digists found\n", maxsessions.len, maxsessions.s);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
return;
} else if (maxsessions_num < disabled) { } else if (maxsessions_num < disabled) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting maxsessions to %d; either positive or -1 values allowed\n", maxsessions_num); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting maxsessions to %d; either positive or -1 values allowed\n", maxsessions_num);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
} else if (maxsessions_num == disabled) { } else if (maxsessions_num == disabled) {
/* don't lock anything while writing the value - only this command modifies its value */ rwlock_lock_w(&m->conf.config_lock);
m->conf.max_sessions = maxsessions_num; m->conf.max_sessions = maxsessions_num;
rwlock_unlock_w(&m->conf.config_lock);
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting maxsessions to %d; disable feature\n", maxsessions_num); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting maxsessions to %d; disable feature\n", maxsessions_num);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
} else { } else {
/* don't lock anything while writing the value - only this command modifies its value */ rwlock_lock_w(&m->conf.config_lock);
m->conf.max_sessions = maxsessions_num; m->conf.max_sessions = maxsessions_num;
rwlock_unlock_w(&m->conf.config_lock);
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting maxsessions to %d\n", maxsessions_num); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting maxsessions to %d\n", maxsessions_num);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
} }
@ -323,6 +379,41 @@ static void cli_incoming_set_maxsessions(char* buffer, int len, struct callmaste
return; return;
} }
static void cli_incoming_set_timeout(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend, unsigned int *conf_timeout) {
int printlen = 0;
unsigned int timeout_num;
str timeout;
char *endptr;
if (len <= 1) {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required.");
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
++buffer; --len; // one space
timeout.s = buffer;
timeout.len = len;
timeout_num = strtol(timeout.s, &endptr, 10);
if ((errno == ERANGE && (timeout_num == LONG_MAX || timeout_num == LONG_MIN)) || (errno != 0 && timeout_num == 0)) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting timeout to %.*s; errno=%d\n", timeout.len, timeout.s, errno);
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
} else if (endptr == timeout.s) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting timeout to %.*s; no digists found\n", timeout.len, timeout.s);
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
} else {
/* don't lock anything while writing the value - only this command modifies its value */
rwlock_lock_w(&m->conf.config_lock);
*conf_timeout = timeout_num;
rwlock_unlock_w(&m->conf.config_lock);
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting timeout to %u\n", timeout_num);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
}
static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
GHashTableIter iter; GHashTableIter iter;
gpointer key, value; gpointer key, value;
@ -336,6 +427,7 @@ static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char*
static const char* LIST_TOTALS = "totals"; static const char* LIST_TOTALS = "totals";
static const char* LIST_MAX_OPEN_FILES = "maxopenfiles"; static const char* LIST_MAX_OPEN_FILES = "maxopenfiles";
static const char* LIST_MAX_SESSIONS = "maxsessions"; static const char* LIST_MAX_SESSIONS = "maxsessions";
static const char* LIST_TIMEOUT = "timeout";
if (len<=1) { if (len<=1) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required."); printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required.");
@ -377,6 +469,8 @@ static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char*
cli_incoming_list_maxsessions(buffer+strlen(LIST_MAX_SESSIONS), len-strlen(LIST_MAX_SESSIONS), m, replybuffer, outbufend); cli_incoming_list_maxsessions(buffer+strlen(LIST_MAX_SESSIONS), len-strlen(LIST_MAX_SESSIONS), m, replybuffer, outbufend);
} else if (len>=strlen(LIST_MAX_OPEN_FILES) && strncmp(buffer,LIST_MAX_OPEN_FILES,strlen(LIST_MAX_OPEN_FILES)) == 0) { } else if (len>=strlen(LIST_MAX_OPEN_FILES) && strncmp(buffer,LIST_MAX_OPEN_FILES,strlen(LIST_MAX_OPEN_FILES)) == 0) {
cli_incoming_list_maxopenfiles(buffer+strlen(LIST_MAX_OPEN_FILES), len-strlen(LIST_MAX_OPEN_FILES), m, replybuffer, outbufend); cli_incoming_list_maxopenfiles(buffer+strlen(LIST_MAX_OPEN_FILES), len-strlen(LIST_MAX_OPEN_FILES), m, replybuffer, outbufend);
} else if (len>=strlen(LIST_TIMEOUT) && strncmp(buffer,LIST_TIMEOUT,strlen(LIST_TIMEOUT)) == 0) {
cli_incoming_list_timeout(buffer+strlen(LIST_TIMEOUT), len-strlen(LIST_TIMEOUT), m, replybuffer, outbufend);
} else { } else {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'list' command", buffer); printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'list' command", buffer);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);
@ -388,6 +482,9 @@ static void cli_incoming_set(char* buffer, int len, struct callmaster* m, char*
static const char* SET_MAX_OPEN_FILES = "maxopenfiles"; static const char* SET_MAX_OPEN_FILES = "maxopenfiles";
static const char* SET_MAX_SESSIONS = "maxsessions"; static const char* SET_MAX_SESSIONS = "maxsessions";
static const char* SET_TIMEOUT = "timeout";
static const char* SET_SILENT_TIMEOUT = "silenttimeout";
static const char* SET_FINAL_TIMEOUT = "finaltimeout";
if (len<=1) { if (len<=1) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required."); printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required.");
@ -400,6 +497,12 @@ static void cli_incoming_set(char* buffer, int len, struct callmaster* m, char*
cli_incoming_set_maxopenfiles(buffer+strlen(SET_MAX_OPEN_FILES), len-strlen(SET_MAX_OPEN_FILES), m, replybuffer, outbufend); cli_incoming_set_maxopenfiles(buffer+strlen(SET_MAX_OPEN_FILES), len-strlen(SET_MAX_OPEN_FILES), m, replybuffer, outbufend);
} else if (len>=strlen(SET_MAX_SESSIONS) && strncmp(buffer,SET_MAX_SESSIONS,strlen(SET_MAX_SESSIONS)) == 0) { } else if (len>=strlen(SET_MAX_SESSIONS) && strncmp(buffer,SET_MAX_SESSIONS,strlen(SET_MAX_SESSIONS)) == 0) {
cli_incoming_set_maxsessions(buffer+strlen(SET_MAX_SESSIONS), len-strlen(SET_MAX_SESSIONS), m, replybuffer, outbufend); cli_incoming_set_maxsessions(buffer+strlen(SET_MAX_SESSIONS), len-strlen(SET_MAX_SESSIONS), m, replybuffer, outbufend);
} else if (len>=strlen(SET_TIMEOUT) && strncmp(buffer,SET_TIMEOUT,strlen(SET_TIMEOUT)) == 0) {
cli_incoming_set_timeout(buffer+strlen(SET_TIMEOUT), len-strlen(SET_TIMEOUT), m, replybuffer, outbufend, &m->conf.timeout);
} else if (len>=strlen(SET_SILENT_TIMEOUT) && strncmp(buffer,SET_SILENT_TIMEOUT,strlen(SET_SILENT_TIMEOUT)) == 0) {
cli_incoming_set_timeout(buffer+strlen(SET_SILENT_TIMEOUT), len-strlen(SET_SILENT_TIMEOUT), m, replybuffer, outbufend, &m->conf.silent_timeout);
} else if (len>=strlen(SET_FINAL_TIMEOUT) && strncmp(buffer,SET_FINAL_TIMEOUT,strlen(SET_FINAL_TIMEOUT)) == 0) {
cli_incoming_set_timeout(buffer+strlen(SET_FINAL_TIMEOUT), len-strlen(SET_FINAL_TIMEOUT), m, replybuffer, outbufend, &m->conf.final_timeout);
} else { } else {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'set' command", buffer); printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'set' command", buffer);
ADJUSTLEN(printlen,outbufend,replybuffer); ADJUSTLEN(printlen,outbufend,replybuffer);

@ -13,6 +13,30 @@
#include "call_interfaces.h" #include "call_interfaces.h"
#include "socket.h" #include "socket.h"
static void timeval_update_request_time(struct request_time *request, const struct timeval *offer_diff) {
// lock offers
mutex_lock(&request->lock);
// update min value
if (timeval_us(&request->time_min) == 0 ||
timeval_cmp(&request->time_min, offer_diff) > 0) {
timeval_from_us(&request->time_min, timeval_us(offer_diff));
}
// update max value
if (timeval_us(&request->time_max) == 0 ||
timeval_cmp(&request->time_max, offer_diff) < 0) {
timeval_from_us(&request->time_max, timeval_us(offer_diff));
}
// update avg value
timeval_add(&request->time_avg, &request->time_avg, offer_diff);
request->count++;
// unlock offers
mutex_unlock(&request->lock);
}
static void pretty_print(bencode_item_t *el, GString *s) { static void pretty_print(bencode_item_t *el, GString *s) {
bencode_item_t *chld; bencode_item_t *chld;
@ -86,6 +110,9 @@ static void control_ng_incoming(struct obj *obj, str *buf, const endpoint_t *sin
struct iovec iov[3]; struct iovec iov[3];
unsigned int iovlen; unsigned int iovlen;
GString *log_str; GString *log_str;
struct timeval offer_start, offer_stop;
struct timeval answer_start, answer_stop;
struct timeval delete_start, delete_stop;
struct control_ng_stats* cur = get_control_ng_stats(c,&sin->address); struct control_ng_stats* cur = get_control_ng_stats(c,&sin->address);
@ -143,16 +170,46 @@ static void control_ng_incoming(struct obj *obj, str *buf, const endpoint_t *sin
g_atomic_int_inc(&cur->ping); g_atomic_int_inc(&cur->ping);
} }
else if (!str_cmp(&cmd, "offer")) { else if (!str_cmp(&cmd, "offer")) {
// start offer timer
gettimeofday(&offer_start, NULL);
errstr = call_offer_ng(dict, c->callmaster, resp, addr, sin); errstr = call_offer_ng(dict, c->callmaster, resp, addr, sin);
g_atomic_int_inc(&cur->offer); g_atomic_int_inc(&cur->offer);
// stop offer timer
gettimeofday(&offer_stop, NULL);
// print offer duration
timeval_from_us(&offer_stop, timeval_diff(&offer_stop, &offer_start));
ilog(LOG_INFO, "offer time = %llu.%06llu sec", (unsigned long long)offer_stop.tv_sec, (unsigned long long)offer_stop.tv_usec);
} }
else if (!str_cmp(&cmd, "answer")) { else if (!str_cmp(&cmd, "answer")) {
// start answer timer
gettimeofday(&answer_start, NULL);
errstr = call_answer_ng(dict, c->callmaster, resp); errstr = call_answer_ng(dict, c->callmaster, resp);
g_atomic_int_inc(&cur->answer); g_atomic_int_inc(&cur->answer);
// stop answer timer
gettimeofday(&answer_stop, NULL);
// print answer duration
timeval_from_us(&answer_stop, timeval_diff(&answer_stop, &answer_start));
ilog(LOG_INFO, "answer time = %llu.%06llu sec", (unsigned long long)answer_stop.tv_sec, (unsigned long long)answer_stop.tv_usec);
} }
else if (!str_cmp(&cmd, "delete")) { else if (!str_cmp(&cmd, "delete")) {
// start delete timer
gettimeofday(&delete_start, NULL);
errstr = call_delete_ng(dict, c->callmaster, resp); errstr = call_delete_ng(dict, c->callmaster, resp);
g_atomic_int_inc(&cur->delete); g_atomic_int_inc(&cur->delete);
// stop delete timer
gettimeofday(&delete_stop, NULL);
// print delete duration
timeval_from_us(&delete_stop, timeval_diff(&delete_stop, &delete_start));
ilog(LOG_INFO, "delete time = %llu.%06llu sec", (unsigned long long)delete_stop.tv_sec, (unsigned long long)delete_stop.tv_usec);
} }
else if (!str_cmp(&cmd, "query")) { else if (!str_cmp(&cmd, "query")) {
errstr = call_query_ng(dict, c->callmaster, resp); errstr = call_query_ng(dict, c->callmaster, resp);
@ -168,6 +225,15 @@ static void control_ng_incoming(struct obj *obj, str *buf, const endpoint_t *sin
if (errstr) if (errstr)
goto err_send; goto err_send;
// update interval statistics
if (!str_cmp(&cmd, "offer")) {
timeval_update_request_time(&c->callmaster->totalstats_interval.offer, &offer_stop);
} else if (!str_cmp(&cmd, "answer")) {
timeval_update_request_time(&c->callmaster->totalstats_interval.answer, &answer_stop);
} else if (!str_cmp(&cmd, "delete")) {
timeval_update_request_time(&c->callmaster->totalstats_interval.delete, &delete_stop);
}
goto send_resp; goto send_resp;
err_send: err_send:

@ -37,6 +37,23 @@ void set_prefix(char* prefix) {
graphite_prefix = prefix; graphite_prefix = prefix;
} }
static struct request_time timeval_clear_request_time(struct request_time *request) {
struct request_time ret;
mutex_lock(&request->lock);
ret = *request;
request->time_min.tv_sec = 0;
request->time_min.tv_usec = 0;
request->time_max.tv_sec = 0;
request->time_max.tv_usec = 0;
request->time_avg.tv_sec = 0;
request->time_avg.tv_usec = 0;
request->count = 0;
mutex_unlock(&request->lock);
return ret;
}
int connect_to_graphite_server(const endpoint_t *graphite_ep) { int connect_to_graphite_server(const endpoint_t *graphite_ep) {
int rc; int rc;
@ -87,6 +104,7 @@ int send_graphite_data(struct callmaster *cm, struct totalstats *sent_data) {
atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_timeout_sess); atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_timeout_sess);
atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_rejected_sess); atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_rejected_sess);
atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_silent_timeout_sess); atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_silent_timeout_sess);
atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_final_timeout_sess);
atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_regular_term_sess); atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_regular_term_sess);
atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_forced_term_sess); atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_forced_term_sess);
atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_relayed_packets); atomic64_local_copy_zero_struct(ts, &cm->totalstats_interval, total_relayed_packets);
@ -105,10 +123,13 @@ int send_graphite_data(struct callmaster *cm, struct totalstats *sent_data) {
ts->total_calls_duration_interval = cm->totalstats_interval.total_calls_duration_interval; ts->total_calls_duration_interval = cm->totalstats_interval.total_calls_duration_interval;
cm->totalstats_interval.total_calls_duration_interval.tv_sec = 0; cm->totalstats_interval.total_calls_duration_interval.tv_sec = 0;
cm->totalstats_interval.total_calls_duration_interval.tv_usec = 0; cm->totalstats_interval.total_calls_duration_interval.tv_usec = 0;
//ZERO(cm->totalstats_interval.total_calls_duration_interval); //ZERO(cm->totalstats_interval.total_calls_duration_interval);
mutex_unlock(&cm->totalstats_interval.total_calls_duration_lock); mutex_unlock(&cm->totalstats_interval.total_calls_duration_lock);
ts->offer = timeval_clear_request_time(&cm->totalstats_interval.offer);
ts->answer = timeval_clear_request_time(&cm->totalstats_interval.answer);
ts->delete = timeval_clear_request_time(&cm->totalstats_interval.delete);
rwlock_lock_r(&cm->hashlock); rwlock_lock_r(&cm->hashlock);
mutex_lock(&cm->totalstats_interval.managed_sess_lock); mutex_lock(&cm->totalstats_interval.managed_sess_lock);
ts->managed_sess_max = cm->totalstats_interval.managed_sess_max; ts->managed_sess_max = cm->totalstats_interval.managed_sess_max;
@ -119,6 +140,32 @@ int send_graphite_data(struct callmaster *cm, struct totalstats *sent_data) {
mutex_unlock(&cm->totalstats_interval.managed_sess_lock); mutex_unlock(&cm->totalstats_interval.managed_sess_lock);
rwlock_unlock_r(&cm->hashlock); rwlock_unlock_r(&cm->hashlock);
// compute average offer/answer/delete time
timeval_divide(&ts->offer.time_avg, &ts->offer.time_avg, ts->offer.count);
timeval_divide(&ts->answer.time_avg, &ts->answer.time_avg, ts->answer.count);
timeval_divide(&ts->delete.time_avg, &ts->delete.time_avg, ts->delete.count);
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"offer_time_min %llu.%06llu %llu\n",(unsigned long long)ts->offer.time_min.tv_sec,(unsigned long long)ts->offer.time_min.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"offer_time_max %llu.%06llu %llu\n",(unsigned long long)ts->offer.time_max.tv_sec,(unsigned long long)ts->offer.time_max.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"offer_time_avg %llu.%06llu %llu\n",(unsigned long long)ts->offer.time_avg.tv_sec,(unsigned long long)ts->offer.time_avg.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"answer_time_min %llu.%06llu %llu\n",(unsigned long long)ts->answer.time_min.tv_sec,(unsigned long long)ts->answer.time_min.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"answer_time_max %llu.%06llu %llu\n",(unsigned long long)ts->answer.time_max.tv_sec,(unsigned long long)ts->answer.time_max.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"answer_time_avg %llu.%06llu %llu\n",(unsigned long long)ts->answer.time_avg.tv_sec,(unsigned long long)ts->answer.time_avg.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"delete_time_min %llu.%06llu %llu\n",(unsigned long long)ts->delete.time_min.tv_sec,(unsigned long long)ts->delete.time_min.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"delete_time_max %llu.%06llu %llu\n",(unsigned long long)ts->delete.time_max.tv_sec,(unsigned long long)ts->delete.time_max.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"delete_time_avg %llu.%06llu %llu\n",(unsigned long long)ts->delete.time_avg.tv_sec,(unsigned long long)ts->delete.time_avg.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr, "call_dur %llu.%06llu %llu\n",(unsigned long long)ts->total_calls_duration_interval.tv_sec,(unsigned long long)ts->total_calls_duration_interval.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc; rc = sprintf(ptr, "call_dur %llu.%06llu %llu\n",(unsigned long long)ts->total_calls_duration_interval.tv_sec,(unsigned long long)ts->total_calls_duration_interval.tv_usec,(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
@ -144,6 +191,8 @@ int send_graphite_data(struct callmaster *cm, struct totalstats *sent_data) {
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; }
rc = sprintf(ptr,"silent_timeout_sess "UINT64F" %llu\n", atomic64_get_na(&ts->total_silent_timeout_sess),(unsigned long long)g_now.tv_sec); ptr += rc; rc = sprintf(ptr,"silent_timeout_sess "UINT64F" %llu\n", atomic64_get_na(&ts->total_silent_timeout_sess),(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } 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)g_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)g_now.tv_sec); ptr += rc; rc = sprintf(ptr,"timeout_sess "UINT64F" %llu\n", atomic64_get_na(&ts->total_timeout_sess),(unsigned long long)g_now.tv_sec); ptr += rc;
if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); 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)g_now.tv_sec); ptr += rc; rc = sprintf(ptr,"reject_sess "UINT64F" %llu\n", atomic64_get_na(&ts->total_rejected_sess),(unsigned long long)g_now.tv_sec); ptr += rc;
@ -155,6 +204,19 @@ int send_graphite_data(struct callmaster *cm, struct totalstats *sent_data) {
(unsigned long long ) ts->total_calls_duration_interval.tv_usec, (unsigned long long ) ts->total_calls_duration_interval.tv_usec,
(unsigned long long ) g_now.tv_sec); (unsigned long long ) g_now.tv_sec);
ilog(LOG_DEBUG, "Min/Max/Avg offer processing delay: %llu.%06llu/%llu.%06llu/%llu.%06llu sec",
(unsigned long long)ts->offer.time_min.tv_sec,(unsigned long long)ts->offer.time_min.tv_usec,
(unsigned long long)ts->offer.time_max.tv_sec,(unsigned long long)ts->offer.time_max.tv_usec,
(unsigned long long)ts->offer.time_avg.tv_sec,(unsigned long long)ts->offer.time_avg.tv_usec);
ilog(LOG_DEBUG, "Min/Max/Avg answer processing delay: %llu.%06llu/%llu.%06llu/%llu.%06llu sec",
(unsigned long long)ts->answer.time_min.tv_sec,(unsigned long long)ts->answer.time_min.tv_usec,
(unsigned long long)ts->answer.time_max.tv_sec,(unsigned long long)ts->answer.time_max.tv_usec,
(unsigned long long)ts->answer.time_avg.tv_sec,(unsigned long long)ts->answer.time_avg.tv_usec);
ilog(LOG_DEBUG, "Min/Max/Avg delete processing delay: %llu.%06llu/%llu.%06llu/%llu.%06llu sec",
(unsigned long long)ts->delete.time_min.tv_sec,(unsigned long long)ts->delete.time_min.tv_usec,
(unsigned long long)ts->delete.time_max.tv_sec,(unsigned long long)ts->delete.time_max.tv_usec,
(unsigned long long)ts->delete.time_avg.tv_sec,(unsigned long long)ts->delete.time_avg.tv_usec);
rc = write(graphite_sock.fd, data_to_send, ptr - data_to_send); rc = write(graphite_sock.fd, data_to_send, ptr - data_to_send);
if (rc<0) { if (rc<0) {
ilog(LOG_ERROR,"Could not write to graphite socket. Disconnecting graphite server."); ilog(LOG_ERROR,"Could not write to graphite socket. Disconnecting graphite server.");

@ -65,8 +65,9 @@ endpoint_t redis_write_ep;
static int tos; static int tos;
static int table = -1; static int table = -1;
static int no_fallback; static int no_fallback;
static int timeout; static unsigned int timeout;
static int silent_timeout; static unsigned int silent_timeout;
static unsigned int final_timeout;
static int port_min = 30000; static int port_min = 30000;
static int port_max = 40000; static int port_max = 40000;
static int max_sessions = -1; static int max_sessions = -1;
@ -290,6 +291,7 @@ static void options(int *argc, char ***argv) {
{ "tos", 'T', 0, G_OPTION_ARG_INT, &tos, "Default TOS value to set on streams", "INT" }, { "tos", 'T', 0, G_OPTION_ARG_INT, &tos, "Default TOS value to set on streams", "INT" },
{ "timeout", 'o', 0, G_OPTION_ARG_INT, &timeout, "RTP timeout", "SECS" }, { "timeout", 'o', 0, G_OPTION_ARG_INT, &timeout, "RTP timeout", "SECS" },
{ "silent-timeout",'s',0,G_OPTION_ARG_INT, &silent_timeout,"RTP timeout for muted", "SECS" }, { "silent-timeout",'s',0,G_OPTION_ARG_INT, &silent_timeout,"RTP timeout for muted", "SECS" },
{ "final-timeout",'a',0,G_OPTION_ARG_INT, &final_timeout, "Call timeout", "SECS" },
{ "pidfile", 'p', 0, G_OPTION_ARG_FILENAME, &pidfile, "Write PID to file", "FILE" }, { "pidfile", 'p', 0, G_OPTION_ARG_FILENAME, &pidfile, "Write PID to file", "FILE" },
{ "foreground", 'f', 0, G_OPTION_ARG_NONE, &foreground, "Don't fork to background", NULL }, { "foreground", 'f', 0, G_OPTION_ARG_NONE, &foreground, "Don't fork to background", NULL },
{ "port-min", 'm', 0, G_OPTION_ARG_INT, &port_min, "Lowest port to use for RTP", "INT" }, { "port-min", 'm', 0, G_OPTION_ARG_INT, &port_min, "Lowest port to use for RTP", "INT" },
@ -377,9 +379,13 @@ static void options(int *argc, char ***argv) {
if (timeout <= 0) if (timeout <= 0)
timeout = 60; timeout = 60;
if (silent_timeout <= 0) if (silent_timeout <= 0)
silent_timeout = 3600; silent_timeout = 3600;
if (final_timeout <= 0)
final_timeout = 0;
if (redisps) if (redisps)
if (redis_ep_parse(&redis_ep, &redis_db, &redis_auth, "RTPENGINE_REDIS_AUTH_PW", redisps)) if (redis_ep_parse(&redis_ep, &redis_db, &redis_auth, "RTPENGINE_REDIS_AUTH_PW", redisps))
die("Invalid Redis endpoint [IP:PORT/INT] (--redis)"); die("Invalid Redis endpoint [IP:PORT/INT] (--redis)");
@ -545,6 +551,7 @@ no_kernel:
dtls_timer(ctx->p); dtls_timer(ctx->p);
ZERO(mc); ZERO(mc);
rwlock_init(&mc.config_lock);
mc.kernelfd = kfd; mc.kernelfd = kfd;
mc.kernelid = table; mc.kernelid = table;
if (max_sessions < -1) { if (max_sessions < -1) {
@ -553,6 +560,7 @@ no_kernel:
mc.max_sessions = max_sessions; mc.max_sessions = max_sessions;
mc.timeout = timeout; mc.timeout = timeout;
mc.silent_timeout = silent_timeout; mc.silent_timeout = silent_timeout;
mc.final_timeout = final_timeout;
mc.delete_delay = delete_delay; mc.delete_delay = delete_delay;
mc.default_tos = tos; mc.default_tos = tos;
mc.b2b_url = b2b_url; mc.b2b_url = b2b_url;

@ -1204,6 +1204,11 @@ loop_ok:
if (MEDIA_ISSET(media, ASYMMETRIC)) if (MEDIA_ISSET(media, ASYMMETRIC))
PS_SET(stream, CONFIRMED); PS_SET(stream, CONFIRMED);
/* confirm sink for unidirectional streams in order to kernelize */
if (MEDIA_ISSET(media, UNIDIRECTIONAL)) {
PS_SET(sink, CONFIRMED);
}
/* if we have already updated the endpoint in the past ... */ /* if we have already updated the endpoint in the past ... */
if (PS_ISSET(stream, CONFIRMED)) { if (PS_ISSET(stream, CONFIRMED)) {
/* see if we need to compare the source address with the known endpoint */ /* see if we need to compare the source address with the known endpoint */

@ -1188,6 +1188,7 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *fl
memcpy(sp->direction, flags->direction, sizeof(sp->direction)); memcpy(sp->direction, flags->direction, sizeof(sp->direction));
sp->desired_family = flags->address_family; sp->desired_family = flags->address_family;
bf_set_clear(&sp->sp_flags, SP_FLAG_ASYMMETRIC, flags->asymmetric); bf_set_clear(&sp->sp_flags, SP_FLAG_ASYMMETRIC, flags->asymmetric);
bf_set_clear(&sp->sp_flags, SP_FLAG_UNIDIRECTIONAL, flags->unidirectional);
bf_set_clear(&sp->sp_flags, SP_FLAG_STRICT_SOURCE, flags->strict_source); bf_set_clear(&sp->sp_flags, SP_FLAG_STRICT_SOURCE, flags->strict_source);
bf_set_clear(&sp->sp_flags, SP_FLAG_MEDIA_HANDOVER, flags->media_handover); bf_set_clear(&sp->sp_flags, SP_FLAG_MEDIA_HANDOVER, flags->media_handover);

@ -8,6 +8,7 @@ LISTEN_CLI=9900
# INTERFACES="12.23.34.45!23.34.45.56" # INTERFACES="12.23.34.45!23.34.45.56"
TIMEOUT=60 TIMEOUT=60
SILENT_TIMEOUT=3600 SILENT_TIMEOUT=3600
# FINAL_TIMEOUT=10800
PIDFILE=/var/run/ngcp-rtpengine-daemon.pid PIDFILE=/var/run/ngcp-rtpengine-daemon.pid
FORK=yes FORK=yes
# TOS=184 # TOS=184

@ -65,6 +65,7 @@ fi
[ -z "$LISTEN_CLI" ] || OPTIONS="$OPTIONS --listen-cli=$LISTEN_CLI" [ -z "$LISTEN_CLI" ] || OPTIONS="$OPTIONS --listen-cli=$LISTEN_CLI"
[ -z "$TIMEOUT" ] || OPTIONS="$OPTIONS --timeout=$TIMEOUT" [ -z "$TIMEOUT" ] || OPTIONS="$OPTIONS --timeout=$TIMEOUT"
[ -z "$SILENT_TIMEOUT" ] || OPTIONS="$OPTIONS --silent-timeout=$SILENT_TIMEOUT" [ -z "$SILENT_TIMEOUT" ] || OPTIONS="$OPTIONS --silent-timeout=$SILENT_TIMEOUT"
[ -z "$FINAL_TIMEOUT" ] || OPTIONS="$OPTIONS --final-timeout=$FINAL_TIMEOUT"
[ -z "$PIDFILE" ] || OPTIONS="$OPTIONS --pidfile=$PIDFILE" [ -z "$PIDFILE" ] || OPTIONS="$OPTIONS --pidfile=$PIDFILE"
[ -z "$TOS" ] || OPTIONS="$OPTIONS --tos=$TOS" [ -z "$TOS" ] || OPTIONS="$OPTIONS --tos=$TOS"
[ -z "$PORT_MIN" ] || OPTIONS="$OPTIONS --port-min=$PORT_MIN" [ -z "$PORT_MIN" ] || OPTIONS="$OPTIONS --port-min=$PORT_MIN"

@ -62,21 +62,25 @@ sub showusage {
print "\n"; print "\n";
print " Supported commands are:\n"; print " Supported commands are:\n";
print "\n"; print "\n";
print " list [ numsessions | maxsessions | maxopenfiles | sessions | session <callid> | totals ]\n"; print " list [ numsessions | maxsessions | maxopenfiles | sessions | session <callid> | totals | timeout ]\n";
print " numsessions : print the number of sessions\n"; print " numsessions : print the number of sessions\n";
print " maxsessions : print the number of allowed sessions\n"; print " maxsessions : print the number of allowed sessions\n";
print " maxopenfiles : print the number of allowed open files\n"; print " maxopenfiles : print the number of allowed open files\n";
print " sessions : print one-liner session information\n"; print " sessions : print one-liner session information\n";
print " session <callid> : print detail about one session\n"; print " session <callid> : print detail about one session\n";
print " totals : print total statistics\n"; print " totals : print total statistics\n";
print " timeout : print timout parameters\n";
print "\n"; print "\n";
print " terminate [ all | <callid> ]\n"; print " terminate [ all | <callid> ]\n";
print " all : terminates all current sessions\n"; print " all : terminates all current sessions\n";
print " <callid> : session is immediately terminated\n"; print " <callid> : session is immediately terminated\n";
print "\n"; print "\n";
print " set [ maxopenfiles <uint> | maxsessions <int> ]\n"; print " set [ maxsessions <int> | maxopenfiles <uint> | timeout <uint> | silent_timeout <uint> | final_timeout <uint>]\n";
print " maxsessions <int> : set the max nr of allowed sessions\n"; print " maxsessions <int> : set the max nr of allowed sessions\n";
print " maxopenfiles <uint> : set the max nr of allowed open files\n"; print " maxopenfiles <uint> : set the max nr of allowed open files\n";
print " timeout <uint> : set the --timeout parameter \n";
print " silenttimeout <uint> : set the --silent-timeout parameter \n";
print " finaltimeout <uint> : set the --final-timeout parameter \n";
print "\n"; print "\n";
print " ksadd [ keyspace <uint>]\n"; print " ksadd [ keyspace <uint>]\n";
print " keyspace <uint> : subscribe to 'keyspace' database\n"; print " keyspace <uint> : subscribe to 'keyspace' database\n";

Loading…
Cancel
Save