diff --git a/daemon/call.c b/daemon/call.c index 934a92143..2a083c854 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -464,6 +464,7 @@ static int streams_parse_func(char **a, void **ret, void *p) { in4_to_6(&st->stream.ip46, ip); st->stream.port = atoi(a[1]); st->stream.num = ++(*i); + st->consecutive_num = 1; if (!st->stream.port && strcmp(a[1], "0")) goto fail; @@ -487,9 +488,8 @@ static void streams_parse(const char *s, struct callmaster *m, GQueue *q) { static void streams_free(GQueue *q) { struct stream_input *s; - while ((s = g_queue_pop_head(q))) { + while ((s = g_queue_pop_head(q))) g_slice_free1(sizeof(*s), s); - } } @@ -1177,6 +1177,8 @@ static void relays_cache_port_used(struct relays_cache *c) { } c->relays_A[c->relays_open].fd = -1; c->relays_B[c->relays_open].fd = -1; + c->relays_A[c->relays_open + 1].fd = -1; + c->relays_B[c->relays_open + 1].fd = -1; } static void relays_cache_cleanup(struct relays_cache *c, struct callmaster *m) { @@ -1252,7 +1254,7 @@ found: if (!matched_relay) { /* nothing found to re-use, use new ports */ - relays_cache_get_ports(&relays_cache, 1, c); + relays_cache_get_ports(&relays_cache, t->consecutive_num, c); callstream_init(cs, &relays_cache); p = &cs->peers[0]; setup_peer(p, t, tag); @@ -1343,7 +1345,7 @@ got_cs: cs_o = cs; cs = callstream_new(c, t->stream.num); mutex_lock(&cs->lock); - relays_cache_get_ports(&relays_cache, 1, c); + relays_cache_get_ports(&relays_cache, t->consecutive_num, c); callstream_init(cs, &relays_cache); steal_peer(&cs->peers[0], &cs_o->peers[0]); p = &cs->peers[1]; @@ -1705,6 +1707,7 @@ static int addr_parse_udp(struct stream_input *st, char **out) { st->stream.num = atoi(out[RE_UDP_UL_NUM]); if (!st->stream.num) st->stream.num = 1; + st->consecutive_num = 1; return 0; fail: diff --git a/daemon/call.h b/daemon/call.h index 669eda719..ce7f7ca7e 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -59,6 +59,7 @@ struct stream { struct stream_input { struct stream stream; enum stream_direction direction[2]; + int consecutive_num; }; struct udp_fd { int fd; diff --git a/daemon/log.h b/daemon/log.h index bbefadf31..5ffdd3668 100644 --- a/daemon/log.h +++ b/daemon/log.h @@ -7,6 +7,7 @@ #define mylog(x,y...) syslog(x,y) #define LOG_ERROR LOG_ERR +#define LOG_WARN LOG_WARNING diff --git a/daemon/sdp.c b/daemon/sdp.c index 2afa2a251..7350b28a7 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -308,7 +308,7 @@ int sdp_streams(const GQueue *sessions, GQueue *streams) { struct stream_input *si; GList *l, *k; const char *errstr; - int i, num; + int i, num, cons_num; num = 0; for (l = sessions->head; l; l = l->next) { @@ -317,6 +317,7 @@ int sdp_streams(const GQueue *sessions, GQueue *streams) { for (k = session->media_streams.head; k; k = k->next) { media = k->data; + cons_num = media->port_count; for (i = 0; i < media->port_count; i++) { si = g_slice_alloc0(sizeof(*si)); @@ -328,10 +329,11 @@ int sdp_streams(const GQueue *sessions, GQueue *streams) { else goto error; - /* XXX ports must be consecutive */ - /* XXX check for RTP type */ + /* we ignore the media type */ si->stream.port = (media->port_num + (i * 2)) & 0xffff; si->stream.num = ++num; + si->consecutive_num = cons_num; + cons_num = 1; g_queue_push_tail(streams, si); } @@ -392,9 +394,11 @@ static int skip_over(struct string_chopper *chop, str *where) { return 0; } -static int replace_port(struct string_chopper *chop, str *port, GList *m, int off) { +static int replace_media_port(struct string_chopper *chop, struct sdp_media *media, GList *m, int off) { struct callstream *cs; struct streamrelay *sr; + str *port = &media->port; + int cons; if (!m) { mylog(LOG_ERROR, "BUG! Ran out of streams"); @@ -412,7 +416,24 @@ static int replace_port(struct string_chopper *chop, str *port, GList *m, int of if (skip_over(chop, port)) return -1; - return 0; + if (media->port_count == 1) + return 1; + + for (cons = 1; cons < media->port_count; cons++) { + m = m->next; + if (!m) + goto warn; + cs = m->data; + if (cs->peers[off].rtps[0].fd.localport != sr->fd.localport + cons * 2) { +warn: + mylog(LOG_WARN, "Failed to handle consecutive ports"); + break; + } + } + + g_string_append_printf(chop->output, "/%i", cons); + + return cons; } static int replace_network_address(struct string_chopper *chop, struct network_address *address, GList *m, int off, struct sdp_ng_flags *flags) { @@ -463,7 +484,7 @@ str *sdp_replace(str *body, GQueue *sessions, struct call *call, int num, enum c struct sdp_media *media; GList *l, *k, *m; struct string_chopper chop; - int off; + int off, skip; off = opmode; if (num < 0) @@ -488,8 +509,8 @@ str *sdp_replace(str *body, GQueue *sessions, struct call *call, int num, enum c for (k = session->media_streams.head; k; k = k->next) { media = k->data; - /* XXX take multiple ports into account */ - if (replace_port(&chop, &media->port, m, off)) + skip = replace_media_port(&chop, media, m, off); + if (skip < 0) goto error; if (media->connection.parsed && flags->replace_sess_conn) { @@ -497,8 +518,7 @@ str *sdp_replace(str *body, GQueue *sessions, struct call *call, int num, enum c goto error; } - if (m) - m = m->next; + m = g_list_nth(m, skip); } }