TT#29151 add 'loop protect' feature

possible fix for: #431, #425, #415, #65

Change-Id: I12558681b7d292e3973d2ba024f30f1e236b3a57
changes/30/18630/1
Richard Fuchs 8 years ago
parent 8f563c8a3c
commit 1477f9796f

@ -1015,6 +1015,14 @@ Optionally included keys are:
Omit the `a=rtcp` line from the outgoing SDP.
- `loop protect`
Inserts a custom attribute (`a=rtpengine:...`) into the outgoing SDP to prevent *rtpengine*
processing and rewriting the same SDP multiple times. This is useful if your setup
involves signalling loops and need to make sure that *rtpengine* doesn't start looping
media packets back to itself. When this flag is present and *rtpengine* sees a matching
attribute already present in the SDP, it will leave the SDP untouched and not process
the message.
* `replace`

@ -608,6 +608,8 @@ static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) {
out->record_call = 1;
else if (!str_cmp(s, "no-rtcp-attribute"))
out->no_rtcp_attr = 1;
else if (!str_cmp(s, "loop-protect"))
out->loop_protect = 1;
else {
// handle values aliases from other dictionaries
if (call_ng_flags_prefix(out, s, "SDES-", ng_sdes_option, NULL))
@ -734,6 +736,13 @@ static const char *call_offer_answer_ng(bencode_item_t *input,
call_ng_process_flags(&flags, input);
flags.opmode = opmode;
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);
errstr = NULL;
goto out;
}
errstr = "Incomplete SDP specification";
if (sdp_streams(&parsed, &streams, &flags))
goto out;

@ -54,6 +54,7 @@ struct sdp_ng_flags {
dtls_passive:1,
reset:1,
record_call:1,
loop_protect:1,
dtls_off:1,
sdes_off:1,
sdes_unencrypted_srtp:1,

@ -201,6 +201,7 @@ struct sdp_attribute {
ATTR_RTPMAP,
ATTR_FMTP,
ATTR_IGNORE,
ATTR_RTPENGINE,
ATTR_END_OF_CANDIDATES,
} attr;
@ -219,6 +220,11 @@ struct sdp_attribute {
static char __id_buf[6*2 + 1]; // 6 hex encoded characters
static const str instance_id = STR_CONST_INIT(__id_buf);
INLINE struct sdp_attribute *attr_get_by_id(struct sdp_attributes *a, int id) {
return g_hash_table_lookup(a->id_hash, &id);
@ -854,6 +860,8 @@ static int parse_attribute(struct sdp_attribute *a) {
ret = parse_attribute_candidate(a);
else if (!str_cmp(&a->name, "ice-ufrag"))
a->attr = ATTR_ICE_UFRAG;
else if (!str_cmp(&a->name, "rtpengine"))
a->attr = ATTR_RTPENGINE;
break;
case 11:
if (!str_cmp(&a->name, "ice-options"))
@ -2005,6 +2013,14 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu
goto error;
}
copy_up_to_end_of(chop, &session->s);
if (flags->loop_protect) {
chopper_append_c(chop, "a=rtpengine:");
chopper_append_str(chop, &instance_id);
chopper_append_c(chop, "\r\n");
}
media_index = 1;
for (k = session->media_streams.head; k; k = k->next) {
@ -2126,5 +2142,24 @@ error:
return -1;
}
int sdp_is_duplicate(GQueue *sessions) {
for (GList *l = sessions->head; l; l = l->next) {
struct sdp_session *s = l->data;
GQueue *attr_list = attr_list_get_by_id(&s->attributes, ATTR_RTPENGINE);
if (!attr_list)
return 0;
for (GList *ql = attr_list->head; ql; ql = ql->next) {
struct sdp_attribute *attr = ql->data;
if (!str_cmp_str(&attr->value, &instance_id))
goto next;
}
return 0;
next:
;
}
return 1;
}
void sdp_init() {
rand_hex_str(instance_id.s, instance_id.len / 2);
}

@ -22,6 +22,7 @@ int sdp_parse(str *body, GQueue *sessions);
int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *);
void sdp_free(GQueue *sessions);
int sdp_replace(struct sdp_chopper *, GQueue *, struct call_monologue *, struct sdp_ng_flags *);
int sdp_is_duplicate(GQueue *sessions);
struct sdp_chopper *sdp_chopper_new(str *input);
void sdp_chopper_destroy(struct sdp_chopper *chop);

@ -43,6 +43,7 @@ GetOptions(
'delete-delay=i' => \$options{'delete-delay'},
'reset' => \$options{'reset'},
'port-latching' => \$options{'port latching'},
'loop-protect' => \$options{'loop protect'},
'media-address=s' => \$options{'media address'},
'codec-strip=s@' => \$options{'codec-strip'},
'codec-offer=s@' => \$options{'codec-offer'},
@ -59,7 +60,7 @@ for my $x (split(/,/, 'from-tag,to-tag,call-id,transport protocol,media address,
for my $x (split(/,/, 'TOS,delete-delay')) {
defined($options{$x}) and $packet{$x} = $options{$x};
}
for my $x (split(/,/, 'trust address,symmetric,asymmetric,force,strict source,media handover,sip source address,reset,port latching,no rtcp attribute')) {
for my $x (split(/,/, 'trust address,symmetric,asymmetric,force,strict source,media handover,sip source address,reset,port latching,no rtcp attribute,loop protect')) {
defined($options{$x}) and push(@{$packet{flags}}, $x);
}
for my $x (split(/,/, 'origin,session connection')) {

Loading…
Cancel
Save