TT#101201 support optional ICE-lite mode

closes #1106

Change-Id: I4a83ed2630889d8b17a0c40d971ec7946c1ed3a2
pull/1116/head
Richard Fuchs 5 years ago
parent 8d7badcf02
commit 1d34c40276

@ -36,6 +36,7 @@ the following additional features are available:
+ Bridging between ICE-enabled and ICE-unaware user agents + Bridging between ICE-enabled and ICE-unaware user agents
+ Optionally acting only as additional ICE relay/candidate + Optionally acting only as additional ICE relay/candidate
+ Optionally forcing relay of media streams by removing other ICE candidates + Optionally forcing relay of media streams by removing other ICE candidates
+ Optionally act as an "ICE lite" peer only
- SRTP (RFC 3711) support: - SRTP (RFC 3711) support:
+ Support for SDES (RFC 4568) and DTLS-SRTP (RFC 5764) + Support for SDES (RFC 4568) and DTLS-SRTP (RFC 5764)
+ AES-CM and AES-F8 ciphers, both in userspace and in kernel + AES-CM and AES-F8 ciphers, both in userspace and in kernel
@ -897,6 +898,21 @@ Optionally included keys are:
This flag operates independently of the `replace` flags. This flag operates independently of the `replace` flags.
* `ICE-lite`
Contains a string which must be one of the following values:
- `forward` to enable "ICE lite" mode towards the peer that this offer is sent to.
- `backward` to enable "ICE lite" mode towards the peer that has sent this offer.
- `both` to enable "ICE lite" towards both peers.
- `off` to disable "ICE lite" towards both peers and revert to full ICE support.
The default (keyword not present at all) is to use full ICE support, or to leave the previously
set "ICE lite" mode unchanged. This keyword is valid in `offer` messages only.
* `transport protocol` * `transport protocol`
The transport protocol specified in the SDP body is to be rewritten to the string value given here. The transport protocol specified in the SDP body is to be rewritten to the string value given here.

@ -1282,23 +1282,46 @@ static void __ice_offer(const struct sdp_ng_flags *flags, struct call_media *thi
} }
} }
switch (flags->ice_lite_option) {
case ICE_LITE_OFF:
MEDIA_CLEAR(this, ICE_LITE_SELF);
MEDIA_CLEAR(other, ICE_LITE_SELF);
break;
case ICE_LITE_FWD:
MEDIA_SET(this, ICE_LITE_SELF);
MEDIA_CLEAR(other, ICE_LITE_SELF);
break;
case ICE_LITE_BKW:
MEDIA_CLEAR(this, ICE_LITE_SELF);
MEDIA_SET(other, ICE_LITE_SELF);
break;
case ICE_LITE_BOTH:
MEDIA_SET(this, ICE_LITE_SELF);
MEDIA_SET(other, ICE_LITE_SELF);
break;
};
/* determine roles (even if we don't actually do ICE) */ /* determine roles (even if we don't actually do ICE) */
/* this = receiver, other = sender */ /* this = receiver, other = sender */
/* ICE_CONTROLLING is from our POV, the other ICE flags are from peer's POV */ /* ICE_CONTROLLING is from our POV, the other ICE flags are from peer's POV */
if (MEDIA_ISSET(this, ICE_LITE_PEER)) if (MEDIA_ISSET(this, ICE_LITE_PEER) && !MEDIA_ISSET(this, ICE_LITE_SELF))
MEDIA_SET(this, ICE_CONTROLLING); MEDIA_SET(this, ICE_CONTROLLING);
else if (!MEDIA_ISSET(this, INITIALIZED)) { else if (!MEDIA_ISSET(this, INITIALIZED)) {
if (flags->opmode == OP_OFFER) if (MEDIA_ISSET(this, ICE_LITE_SELF))
MEDIA_CLEAR(this, ICE_CONTROLLING);
else if (flags->opmode == OP_OFFER)
MEDIA_SET(this, ICE_CONTROLLING); MEDIA_SET(this, ICE_CONTROLLING);
else else
MEDIA_CLEAR(this, ICE_CONTROLLING); MEDIA_CLEAR(this, ICE_CONTROLLING);
} }
/* roles are reversed for the other side */ /* roles are reversed for the other side */
if (MEDIA_ISSET(other, ICE_LITE_PEER)) if (MEDIA_ISSET(other, ICE_LITE_PEER) && !MEDIA_ISSET(other, ICE_LITE_SELF))
MEDIA_SET(other, ICE_CONTROLLING); MEDIA_SET(other, ICE_CONTROLLING);
else if (!MEDIA_ISSET(other, INITIALIZED)) { else if (!MEDIA_ISSET(other, INITIALIZED)) {
if (flags->opmode == OP_OFFER) if (MEDIA_ISSET(other, ICE_LITE_SELF))
MEDIA_CLEAR(other, ICE_CONTROLLING);
else if (flags->opmode == OP_OFFER)
MEDIA_CLEAR(other, ICE_CONTROLLING); MEDIA_CLEAR(other, ICE_CONTROLLING);
else else
MEDIA_SET(other, ICE_CONTROLLING); MEDIA_SET(other, ICE_CONTROLLING);

@ -949,6 +949,37 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu
} }
} }
if (bencode_dictionary_get_str(input, "ICE-lite", &s)) {
switch (__csh_lookup(&s)) {
case CSH_LOOKUP("off"):
case CSH_LOOKUP("none"):
case CSH_LOOKUP("no"):
out->ice_lite_option = ICE_LITE_OFF;
break;
case CSH_LOOKUP("forward"):
case CSH_LOOKUP("offer"):
case CSH_LOOKUP("fwd"):
case CSH_LOOKUP("fw"):
out->ice_lite_option = ICE_LITE_FWD;
break;
case CSH_LOOKUP("backward"):
case CSH_LOOKUP("backwards"):
case CSH_LOOKUP("reverse"):
case CSH_LOOKUP("answer"):
case CSH_LOOKUP("back"):
case CSH_LOOKUP("bkw"):
case CSH_LOOKUP("bk"):
out->ice_lite_option = ICE_LITE_BKW;
break;
case CSH_LOOKUP("both"):
out->ice_lite_option = ICE_LITE_BOTH;
break;
default:
ilog(LOG_WARN, "Unknown 'ICE-lite' flag encountered: '" STR_FORMAT "'",
STR_FMT(&s));
}
}
if (bencode_dictionary_get_str(input, "DTLS", &s)) { if (bencode_dictionary_get_str(input, "DTLS", &s)) {
switch (__csh_lookup(&s)) { switch (__csh_lookup(&s)) {
case CSH_LOOKUP("passive"): case CSH_LOOKUP("passive"):

@ -237,6 +237,7 @@ static void __ice_agent_initialize(struct ice_agent *ag) {
ag->foundation_hash = g_hash_table_new(__found_hash, __found_equal); ag->foundation_hash = g_hash_table_new(__found_hash, __found_equal);
ag->agent_flags = 0; ag->agent_flags = 0;
bf_copy(&ag->agent_flags, ICE_AGENT_CONTROLLING, &media->media_flags, MEDIA_FLAG_ICE_CONTROLLING); bf_copy(&ag->agent_flags, ICE_AGENT_CONTROLLING, &media->media_flags, MEDIA_FLAG_ICE_CONTROLLING);
bf_copy(&ag->agent_flags, ICE_AGENT_LITE_SELF, &media->media_flags, MEDIA_FLAG_ICE_LITE_SELF);
ag->logical_intf = media->logical_intf; ag->logical_intf = media->logical_intf;
ag->desired_family = media->desired_family; ag->desired_family = media->desired_family;
ag->nominated_pairs = g_tree_new(__pair_prio_cmp); ag->nominated_pairs = g_tree_new(__pair_prio_cmp);
@ -579,6 +580,9 @@ static void __do_ice_check(struct ice_candidate_pair *pair) {
struct ice_agent *ag = pair->agent; struct ice_agent *ag = pair->agent;
u_int32_t prio, transact[3]; u_int32_t prio, transact[3];
if (AGENT_ISSET(ag, LITE_SELF))
PAIR_SET(pair, SUCCEEDED);
if (PAIR_ISSET(pair, SUCCEEDED) && !PAIR_ISSET(pair, TO_USE)) if (PAIR_ISSET(pair, SUCCEEDED) && !PAIR_ISSET(pair, TO_USE))
return; return;
@ -1096,19 +1100,23 @@ int ice_request(struct stream_fd *sfd, const endpoint_t *src,
mutex_unlock(&ag->lock); mutex_unlock(&ag->lock);
/* determine role conflict */ if (!AGENT_ISSET(ag, LITE_SELF)) {
if (attrs->controlling && AGENT_ISSET(ag, CONTROLLING)) { /* determine role conflict */
if (tie_breaker >= attrs->tiebreaker) if (attrs->controlling && AGENT_ISSET(ag, CONTROLLING)) {
return -2; if (tie_breaker >= attrs->tiebreaker)
else return -2;
__role_change(ag, 0); else
} __role_change(ag, 0);
else if (attrs->controlled && !AGENT_ISSET(ag, CONTROLLING)) { }
if (tie_breaker >= attrs->tiebreaker) else if (attrs->controlled && !AGENT_ISSET(ag, CONTROLLING)) {
__role_change(ag, 1); if (tie_breaker >= attrs->tiebreaker)
else __role_change(ag, 1);
return -2; else
return -2;
}
} }
else
PAIR_SET(pair, SUCCEEDED);
if (PAIR_ISSET(pair, SUCCEEDED)) if (PAIR_ISSET(pair, SUCCEEDED))

@ -2370,6 +2370,9 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu
chopper_append_c(chop, "\r\n"); chopper_append_c(chop, "\r\n");
} }
if (MEDIA_ISSET(call_media, ICE) && MEDIA_ISSET(call_media, ICE_LITE_SELF))
chopper_append_c(chop, "a=ice-lite\r\n");
media_index = 1; media_index = 1;
for (k = session->media_streams.head; k; k = k->next) { for (k = session->media_streams.head; k; k = k->next) {

@ -153,6 +153,7 @@ enum call_type {
#define MEDIA_FLAG_PTIME_OVERRIDE 0x01000000 #define MEDIA_FLAG_PTIME_OVERRIDE 0x01000000
#define MEDIA_FLAG_RTCP_FB SHARED_FLAG_RTCP_FB #define MEDIA_FLAG_RTCP_FB SHARED_FLAG_RTCP_FB
#define MEDIA_FLAG_GENERATOR 0x02000000 #define MEDIA_FLAG_GENERATOR 0x02000000
#define MEDIA_FLAG_ICE_LITE_SELF 0x04000000
/* access macros */ /* access macros */
#define SP_ISSET(p, f) bf_isset(&(p)->sp_flags, SP_FLAG_ ## f) #define SP_ISSET(p, f) bf_isset(&(p)->sp_flags, SP_FLAG_ ## f)

@ -54,6 +54,12 @@ struct sdp_ng_flags {
ICE_FORCE_RELAY, ICE_FORCE_RELAY,
ICE_OPTIONAL, ICE_OPTIONAL,
} ice_option:3; } ice_option:3;
enum {
ICE_LITE_OFF = 0,
ICE_LITE_FWD,
ICE_LITE_BKW,
ICE_LITE_BOTH,
} ice_lite_option:2;
int asymmetric:1, int asymmetric:1,
protocol_accept:1, protocol_accept:1,
no_redis_update:1, no_redis_update:1,

@ -30,6 +30,7 @@
#define ICE_AGENT_CONTROLLING 0x0004 #define ICE_AGENT_CONTROLLING 0x0004
#define ICE_AGENT_NOMINATING 0x0008 #define ICE_AGENT_NOMINATING 0x0008
#define ICE_AGENT_USABLE 0x0010 #define ICE_AGENT_USABLE 0x0010
#define ICE_AGENT_LITE_SELF 0x0020
#define ICE_PAIR_FROZEN 0x0001 #define ICE_PAIR_FROZEN 0x0001
#define ICE_PAIR_IN_PROGRESS 0x0002 #define ICE_PAIR_IN_PROGRESS 0x0002

@ -77,13 +77,14 @@ GetOptions(
'symmetric-codecs' => \$options{'symmetric codecs'}, 'symmetric-codecs' => \$options{'symmetric codecs'},
'asymmetric-codecs' => \$options{'asymmetric codecs'}, 'asymmetric-codecs' => \$options{'asymmetric codecs'},
'DTLS-fingerprint=s' => \$options{'DTLS-fingerprint'}, 'DTLS-fingerprint=s' => \$options{'DTLS-fingerprint'},
'ICE-lite=s' => \$options{'ICE-lite'},
) or die; ) or die;
my $cmd = shift(@ARGV) or die; my $cmd = shift(@ARGV) or die;
my %packet = (command => $cmd); my %packet = (command => $cmd);
for my $x (split(/,/, 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,DTLS,via-branch,media address,ptime,xmlrpc-callback,metadata,address,file,db-id,code,DTLS-fingerprint')) { for my $x (split(/,/, 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,DTLS,via-branch,media address,ptime,xmlrpc-callback,metadata,address,file,db-id,code,DTLS-fingerprint,ICE-lite')) {
defined($options{$x}) and $packet{$x} = \$options{$x}; defined($options{$x}) and $packet{$x} = \$options{$x};
} }
for my $x (split(/,/, 'TOS,delete-delay')) { for my $x (split(/,/, 'TOS,delete-delay')) {

Loading…
Cancel
Save