|
|
|
|
@ -17,6 +17,7 @@
|
|
|
|
|
#include "str.h"
|
|
|
|
|
#include "control_tcp.h"
|
|
|
|
|
#include "control_udp.h"
|
|
|
|
|
#include "control_ng.h"
|
|
|
|
|
#include "rtp.h"
|
|
|
|
|
#include "ice.h"
|
|
|
|
|
#include "recording.h"
|
|
|
|
|
@ -558,6 +559,10 @@ static void call_ng_flags_replace(struct sdp_ng_flags *out, str *s, void *dummy)
|
|
|
|
|
ilog(LOG_WARN, "Unknown 'replace' flag encountered: '" STR_FORMAT "'",
|
|
|
|
|
STR_FMT(s));
|
|
|
|
|
}
|
|
|
|
|
static void call_ng_flags_supports(struct sdp_ng_flags *out, str *s, void *dummy) {
|
|
|
|
|
if (!str_cmp(s, "load limit"))
|
|
|
|
|
out->supports_load_limit = 1;
|
|
|
|
|
}
|
|
|
|
|
static void call_ng_flags_codec_list(struct sdp_ng_flags *out, str *s, void *qp) {
|
|
|
|
|
str *s_copy;
|
|
|
|
|
s_copy = g_slice_alloc(sizeof(*s_copy));
|
|
|
|
|
@ -646,6 +651,7 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu
|
|
|
|
|
|
|
|
|
|
call_ng_flags_list(out, input, "flags", call_ng_flags_flags, NULL);
|
|
|
|
|
call_ng_flags_list(out, input, "replace", call_ng_flags_replace, NULL);
|
|
|
|
|
call_ng_flags_list(out, input, "supports", call_ng_flags_supports, NULL);
|
|
|
|
|
|
|
|
|
|
diridx = 0;
|
|
|
|
|
if ((list = bencode_dictionary_get_expect(input, "direction", BENCODE_LIST))) {
|
|
|
|
|
@ -714,13 +720,38 @@ static void call_ng_free_flags(struct sdp_ng_flags *flags) {
|
|
|
|
|
g_queue_clear_full(&flags->codec_transcode, str_slice_free);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum load_limit_reasons call_offer_session_limit(void) {
|
|
|
|
|
enum load_limit_reasons ret = LOAD_LIMIT_NONE;
|
|
|
|
|
|
|
|
|
|
rwlock_lock_r(&rtpe_config.config_lock);
|
|
|
|
|
if (rtpe_config.max_sessions>=0) {
|
|
|
|
|
rwlock_lock_r(&rtpe_callhash_lock);
|
|
|
|
|
if (g_hash_table_size(rtpe_callhash) -
|
|
|
|
|
atomic64_get(&rtpe_stats.foreign_sessions) >= rtpe_config.max_sessions)
|
|
|
|
|
{
|
|
|
|
|
/* foreign calls can't get rejected
|
|
|
|
|
* total_rejected_sess applies only to "own" sessions */
|
|
|
|
|
atomic64_inc(&rtpe_totalstats.total_rejected_sess);
|
|
|
|
|
atomic64_inc(&rtpe_totalstats_interval.total_rejected_sess);
|
|
|
|
|
ilog(LOG_ERROR, "Parallel session limit reached (%i)",rtpe_config.max_sessions);
|
|
|
|
|
|
|
|
|
|
ret = LOAD_LIMIT_MAX_SESSIONS;
|
|
|
|
|
}
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rwlock_unlock_r(&rtpe_config.config_lock);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *call_offer_answer_ng(bencode_item_t *input,
|
|
|
|
|
bencode_item_t *output, enum call_opmode opmode, const char* addr,
|
|
|
|
|
const endpoint_t *sin)
|
|
|
|
|
{
|
|
|
|
|
str sdp, fromtag, totag = STR_NULL, callid, viabranch;
|
|
|
|
|
str label = STR_NULL;
|
|
|
|
|
char *errstr;
|
|
|
|
|
const char *errstr;
|
|
|
|
|
GQueue parsed = G_QUEUE_INIT;
|
|
|
|
|
GQueue streams = G_QUEUE_INIT;
|
|
|
|
|
struct call *call;
|
|
|
|
|
@ -744,12 +775,24 @@ static const char *call_offer_answer_ng(bencode_item_t *input,
|
|
|
|
|
bencode_dictionary_get_str(input, "via-branch", &viabranch);
|
|
|
|
|
bencode_dictionary_get_str(input, "label", &label);
|
|
|
|
|
|
|
|
|
|
if (sdp_parse(&sdp, &parsed))
|
|
|
|
|
return "Failed to parse SDP";
|
|
|
|
|
|
|
|
|
|
call_ng_process_flags(&flags, input);
|
|
|
|
|
flags.opmode = opmode;
|
|
|
|
|
|
|
|
|
|
if (opmode == OP_OFFER) {
|
|
|
|
|
enum load_limit_reasons limit = call_offer_session_limit();
|
|
|
|
|
if (limit != LOAD_LIMIT_NONE) {
|
|
|
|
|
if (!flags.supports_load_limit)
|
|
|
|
|
errstr = "Parallel session limit reached"; // legacy protocol
|
|
|
|
|
else
|
|
|
|
|
errstr = magic_load_limit_strings[limit];
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errstr = "Failed to parse SDP";
|
|
|
|
|
if (sdp_parse(&sdp, &parsed))
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
if (flags.loop_protect && sdp_is_duplicate(&parsed)) {
|
|
|
|
|
ilog(LOG_INFO, "Ignoring message as SDP has already been processed by us");
|
|
|
|
|
bencode_dictionary_add_str(output, "sdp", &sdp);
|
|
|
|
|
@ -874,25 +917,6 @@ out:
|
|
|
|
|
const char *call_offer_ng(bencode_item_t *input, bencode_item_t *output, const char* addr,
|
|
|
|
|
const endpoint_t *sin)
|
|
|
|
|
{
|
|
|
|
|
rwlock_lock_r(&rtpe_config.config_lock);
|
|
|
|
|
if (rtpe_config.max_sessions>=0) {
|
|
|
|
|
rwlock_lock_r(&rtpe_callhash_lock);
|
|
|
|
|
if (g_hash_table_size(rtpe_callhash) -
|
|
|
|
|
atomic64_get(&rtpe_stats.foreign_sessions) >= rtpe_config.max_sessions) {
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
/* foreign calls can't get rejected
|
|
|
|
|
* total_rejected_sess applies only to "own" sessions */
|
|
|
|
|
atomic64_inc(&rtpe_totalstats.total_rejected_sess);
|
|
|
|
|
atomic64_inc(&rtpe_totalstats_interval.total_rejected_sess);
|
|
|
|
|
ilog(LOG_ERROR, "Parallel session limit reached (%i)",rtpe_config.max_sessions);
|
|
|
|
|
|
|
|
|
|
rwlock_unlock_r(&rtpe_config.config_lock);
|
|
|
|
|
return "Parallel session limit reached";
|
|
|
|
|
}
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rwlock_unlock_r(&rtpe_config.config_lock);
|
|
|
|
|
return call_offer_answer_ng(input, output, OP_OFFER, addr, sin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|