diff --git a/daemon/call.c b/daemon/call.c index 041128100..7144ee70a 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2397,7 +2397,8 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, /* copy parameters advertised by the sender of this message */ 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_ICE + | SHARED_FLAG_TRICKLE_ICE); crypto_params_copy(&other_media->sdes_in.params, &sp->crypto); other_media->sdes_in.tag = sp->sdes_tag; @@ -2457,7 +2458,7 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, __disable_streams(other_media, num_ports); goto init; } - if (is_addr_unspecified(&sp->rtp_endpoint.ip46)) { + if (is_addr_unspecified(&sp->rtp_endpoint.ip46) && !is_trickle_ice_address(&sp->rtp_endpoint)) { /* Zero endpoint address, equivalent to setting the media stream * to sendonly or inactive */ MEDIA_CLEAR(media, RECV); @@ -2856,7 +2857,7 @@ static int call_stream_address4(char *o, struct packet_stream *ps, enum stream_a l = 4; } - if (!in6_to_4(&ps->advertised_endpoint.ip46)) { + if (!in6_to_4(&ps->advertised_endpoint.ip46) && !is_trickle_ice_address(&ps->advertised_endpoint)) { strcpy(o + l, "0.0.0.0"); l += 7; } @@ -2879,7 +2880,8 @@ static int call_stream_address6(char *o, struct packet_stream *ps, enum stream_a l += 4; } - if (is_addr_unspecified(&ps->advertised_endpoint.ip46)) { + if (is_addr_unspecified(&ps->advertised_endpoint.ip46) + && !is_trickle_ice_address(&ps->advertised_endpoint)) { strcpy(o + l, "::"); l += 2; } diff --git a/daemon/call.h b/daemon/call.h index 057d4a2be..05c0321f1 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -104,6 +104,7 @@ struct call_monologue; #define SHARED_FLAG_ICE 0x00000080 #define SHARED_FLAG_STRICT_SOURCE 0x00000100 #define SHARED_FLAG_MEDIA_HANDOVER 0x00000200 +#define SHARED_FLAG_TRICKLE_ICE 0x00000400 /* struct stream_params */ #define SP_FLAG_NO_RTCP 0x00010000 @@ -117,6 +118,7 @@ struct call_monologue; #define SP_FLAG_ICE SHARED_FLAG_ICE #define SP_FLAG_STRICT_SOURCE SHARED_FLAG_STRICT_SOURCE #define SP_FLAG_MEDIA_HANDOVER SHARED_FLAG_MEDIA_HANDOVER +#define SP_FLAG_TRICKLE_ICE SHARED_FLAG_TRICKLE_ICE /* struct packet_stream */ #define PS_FLAG_RTP 0x00010000 @@ -146,6 +148,7 @@ struct call_monologue; #define MEDIA_FLAG_SETUP_PASSIVE SHARED_FLAG_SETUP_PASSIVE #define MEDIA_FLAG_PASSTHRU 0x00100000 #define MEDIA_FLAG_ICE SHARED_FLAG_ICE +#define MEDIA_FLAG_TRICKLE_ICE SHARED_FLAG_TRICKLE_ICE /* access macros */ #define SP_ISSET(p, f) bf_isset(&(p)->sp_flags, SP_FLAG_ ## f) diff --git a/daemon/sdp.c b/daemon/sdp.c index e951ca4a5..45820d790 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -166,6 +166,7 @@ struct sdp_attribute { ATTR_RTCP, ATTR_CANDIDATE, ATTR_ICE, + ATTR_ICE_OPTIONS, ATTR_ICE_UFRAG, ATTR_CRYPTO, ATTR_SSRC, @@ -797,7 +798,7 @@ static int parse_attribute(struct sdp_attribute *a) { break; case 11: if (!str_cmp(&a->name, "ice-options")) - a->attr = ATTR_ICE; + a->attr = ATTR_ICE_OPTIONS; else if (!str_cmp(&a->name, "fingerprint")) ret = parse_attribute_fingerprint(a); break; @@ -1180,9 +1181,15 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *fl sp->fingerprint.hash_func->num_bytes); } - /* a=candidate */ + /* ICE stuff */ if (attr_get_by_id(&media->attributes, ATTR_CANDIDATE)) SP_SET(sp, ICE); + if ((attr = attr_get_by_id(&media->attributes, ATTR_ICE_OPTIONS))) { + if (str_str(&attr->value, "trickle") >= 0) + SP_SET(sp, TRICKLE_ICE); + } + else if (is_trickle_ice_address(&sp->rtp_endpoint)) + SP_SET(sp, TRICKLE_ICE); /* determine RTCP endpoint */ @@ -1386,8 +1393,10 @@ static int replace_network_address(struct sdp_chopper *chop, struct network_addr { char buf[64]; int len; + struct packet_stream *sink = packet_stream_sink(ps); - if (is_addr_unspecified(&address->parsed)) + if (is_addr_unspecified(&address->parsed) + && !(sink && is_trickle_ice_address(&sink->advertised_endpoint))) return 0; if (copy_up_to(chop, &address->address_type)) diff --git a/daemon/sdp.h b/daemon/sdp.h index 272c4eae1..ab659f17b 100644 --- a/daemon/sdp.h +++ b/daemon/sdp.h @@ -57,4 +57,10 @@ void sdp_chopper_destroy(struct sdp_chopper *chop); int address_family(const str *s); +INLINE int is_trickle_ice_address(const struct endpoint *ep) { + if (is_addr_unspecified(&ep->ip46) && ep->port == 9) + return 1; + return 0; +} + #endif diff --git a/daemon/str.h b/daemon/str.h index 20e1cda5b..2225767c0 100644 --- a/daemon/str.h +++ b/daemon/str.h @@ -57,6 +57,8 @@ INLINE str *str_chunk_insert(GStringChunk *c, const str *s); INLINE int str_shift(str *s, int len); /* binary compares str object with memory chunk of equal size */ INLINE int str_memcmp(const str *s, void *m); +/* locate a substring within a string, returns character index or -1 */ +INLINE int str_str(const str *s, const char *sub); /* asprintf() analogs */ #define str_sprintf(fmt, a...) __str_sprintf(STR_MALLOC_PADDING fmt, a) @@ -212,5 +214,22 @@ INLINE str *g_string_free_str(GString *gs) { INLINE int str_memcmp(const str *s, void *m) { return memcmp(s->s, m, s->len); } +INLINE int str_str(const str *s, const char *sub) { + int len = strlen(sub); + void *p, *e; + + p = s->s; + e = p + (s->len - len); + while (p < e) { + p = memchr(p, sub[0], e - p); + if (!p) + return -1; + if (!memcmp(p, sub, len)) + return p - (void *) s->s; + p++; + } + + return -1; +} #endif