|
|
|
@ -968,7 +968,7 @@ alloc: |
|
|
|
"affinity: %s", strerror(errno)); |
|
|
|
} |
|
|
|
sfd = stream_fd_new(sock, media->call, il->local_intf); |
|
|
|
g_queue_push_tail(&em_il->list, sfd); /* not referenced */ |
|
|
|
g_queue_push_tail(&em_il->list, sfd); // not referenced |
|
|
|
} |
|
|
|
|
|
|
|
next_il: |
|
|
|
@ -988,20 +988,26 @@ static void __assign_stream_fds(struct call_media *media, GQueue *intf_sfds) { |
|
|
|
void *old_selected_sfd = ps->selected_sfd; |
|
|
|
|
|
|
|
g_queue_clear(&ps->sfds); |
|
|
|
int sfd_found = 0; |
|
|
|
bool sfd_found = false; |
|
|
|
struct stream_fd *intf_sfd = NULL; |
|
|
|
|
|
|
|
for (GList *l = intf_sfds->head; l; l = l->next) { |
|
|
|
struct intf_list *il = l->data; |
|
|
|
|
|
|
|
struct stream_fd *sfd = g_queue_peek_nth(&il->list, ps->component - 1); |
|
|
|
if (!sfd) return ; |
|
|
|
if (!sfd) { |
|
|
|
// create a dummy sfd. needed to hold RTCP crypto context when |
|
|
|
// RTCP-mux is in use |
|
|
|
socket_t *sock = g_slice_alloc(sizeof(*sock)); |
|
|
|
dummy_socket(sock, &il->local_intf->spec->local_address.addr); |
|
|
|
sfd = stream_fd_new(sock, media->call, il->local_intf); |
|
|
|
} |
|
|
|
|
|
|
|
sfd->stream = ps; |
|
|
|
g_queue_push_tail(&ps->sfds, sfd); |
|
|
|
|
|
|
|
if (ps->selected_sfd == sfd) |
|
|
|
sfd_found = 1; |
|
|
|
sfd_found = true; |
|
|
|
if (ps->selected_sfd && sfd->local_intf == ps->selected_sfd->local_intf) |
|
|
|
intf_sfd = sfd; |
|
|
|
} |
|
|
|
@ -1060,6 +1066,10 @@ static int __num_media_streams(struct call_media *media, unsigned int num_ports) |
|
|
|
struct call *call = media->call; |
|
|
|
int ret = 0; |
|
|
|
|
|
|
|
// we need at least two, one for RTP and one for RTCP as they hold the crypto context |
|
|
|
if (num_ports < 2) |
|
|
|
num_ports = 2; |
|
|
|
|
|
|
|
__C_DBG("allocating %i new packet_streams", num_ports - media->streams.length); |
|
|
|
while (media->streams.length < num_ports) { |
|
|
|
stream = __packet_stream_new(call); |
|
|
|
@ -2639,6 +2649,27 @@ static int __media_init_from_flags(struct call_media *other_media, struct call_m |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
unsigned int proto_num_ports(unsigned int sp_ports, struct call_media *media, struct sdp_ng_flags *flags, |
|
|
|
bool allow_offer_split) |
|
|
|
{ |
|
|
|
if (sp_ports != 2) |
|
|
|
return sp_ports; |
|
|
|
if (!proto_is_rtp(media->protocol)) |
|
|
|
return sp_ports; |
|
|
|
if (!MEDIA_ISSET(media, RTCP_MUX)) |
|
|
|
return sp_ports; |
|
|
|
if (!flags) |
|
|
|
return sp_ports; |
|
|
|
if (flags->opmode == OP_ANSWER || flags->opmode == OP_PUBLISH) |
|
|
|
return sp_ports / 2; |
|
|
|
if (flags->opmode == OP_OFFER) { |
|
|
|
if (allow_offer_split) |
|
|
|
return sp_ports / 2; |
|
|
|
return sp_ports; |
|
|
|
} |
|
|
|
return sp_ports; |
|
|
|
} |
|
|
|
|
|
|
|
/* called with call->master_lock held in W */ |
|
|
|
int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, |
|
|
|
struct sdp_ng_flags *flags) |
|
|
|
@ -2649,6 +2680,7 @@ int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, |
|
|
|
struct endpoint_map *em; |
|
|
|
struct call_monologue *other_ml = dialogue[0]; |
|
|
|
struct call_monologue *monologue = dialogue[1]; |
|
|
|
unsigned int num_ports_this, num_ports_other; |
|
|
|
|
|
|
|
/* we must have a complete dialogue, even though the to-tag (monologue->tag) |
|
|
|
* may not be known yet */ |
|
|
|
@ -2714,9 +2746,13 @@ int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
num_ports_this = proto_num_ports(sp->num_ports, media, flags, |
|
|
|
flags && flags->rtcp_mux_require ? true : false); |
|
|
|
num_ports_other = proto_num_ports(sp->num_ports, other_media, flags, false); |
|
|
|
|
|
|
|
/* local interface selection */ |
|
|
|
__init_interface(media, &sp->direction[1], sp->num_ports); |
|
|
|
__init_interface(other_media, &sp->direction[0], sp->num_ports); |
|
|
|
__init_interface(media, &sp->direction[1], num_ports_this); |
|
|
|
__init_interface(other_media, &sp->direction[0], num_ports_other); |
|
|
|
|
|
|
|
if (media->logical_intf == NULL || other_media->logical_intf == NULL) { |
|
|
|
goto error_intf; |
|
|
|
@ -2735,8 +2771,8 @@ int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, |
|
|
|
* RFC 3264, chapter 6: |
|
|
|
* If a stream is rejected, the offerer and answerer MUST NOT |
|
|
|
* generate media (or RTCP packets) for that stream. */ |
|
|
|
__disable_streams(media, sp->num_ports); |
|
|
|
__disable_streams(other_media, sp->num_ports); |
|
|
|
__disable_streams(media, num_ports_this); |
|
|
|
__disable_streams(other_media, num_ports_other); |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (is_addr_unspecified(&sp->rtp_endpoint.address) && !MEDIA_ISSET(other_media, TRICKLE_ICE)) { |
|
|
|
@ -2749,7 +2785,7 @@ int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, |
|
|
|
|
|
|
|
/* get that many ports for each side, and one packet stream for each port, then |
|
|
|
* assign the ports to the streams */ |
|
|
|
em = __get_endpoint_map(media, sp->num_ports, &sp->rtp_endpoint, flags, false); |
|
|
|
em = __get_endpoint_map(media, num_ports_this, &sp->rtp_endpoint, flags, false); |
|
|
|
if (!em) { |
|
|
|
goto error_ports; |
|
|
|
} |
|
|
|
@ -2757,14 +2793,14 @@ int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, |
|
|
|
if(flags->disable_jb && media->call) |
|
|
|
media->call->disable_jb=1; |
|
|
|
|
|
|
|
__num_media_streams(media, sp->num_ports); |
|
|
|
__num_media_streams(media, num_ports_this); |
|
|
|
__assign_stream_fds(media, &em->intf_sfds); |
|
|
|
|
|
|
|
if (__num_media_streams(other_media, sp->num_ports)) { |
|
|
|
if (__num_media_streams(other_media, num_ports_other)) { |
|
|
|
/* new streams created on OTHER side. normally only happens in |
|
|
|
* initial offer. create a wildcard endpoint_map to be filled in |
|
|
|
* when the answer comes. */ |
|
|
|
if (__wildcard_endpoint_map(other_media, sp->num_ports)) |
|
|
|
if (__wildcard_endpoint_map(other_media, num_ports_other)) |
|
|
|
goto error_ports; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -2906,8 +2942,10 @@ int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_ |
|
|
|
__generate_crypto(flags, media, NULL); |
|
|
|
} |
|
|
|
|
|
|
|
unsigned int num_ports = proto_num_ports(sp->num_ports, media, flags, true); |
|
|
|
|
|
|
|
/* local interface selection */ |
|
|
|
__init_interface(media, &flags->interface, sp->num_ports); |
|
|
|
__init_interface(media, &flags->interface, num_ports); |
|
|
|
|
|
|
|
if (media->logical_intf == NULL) |
|
|
|
return -1; // XXX return error code |
|
|
|
@ -2922,15 +2960,15 @@ int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_ |
|
|
|
* RFC 3264, chapter 6: |
|
|
|
* If a stream is rejected, the offerer and answerer MUST NOT |
|
|
|
* generate media (or RTCP packets) for that stream. */ |
|
|
|
__disable_streams(media, sp->num_ports); |
|
|
|
__disable_streams(media, num_ports); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
struct endpoint_map *em = __get_endpoint_map(media, sp->num_ports, NULL, flags, true); |
|
|
|
struct endpoint_map *em = __get_endpoint_map(media, num_ports, NULL, flags, true); |
|
|
|
if (!em) |
|
|
|
return -1; // XXX error - no ports |
|
|
|
|
|
|
|
__num_media_streams(media, sp->num_ports); |
|
|
|
__num_media_streams(media, num_ports); |
|
|
|
__assign_stream_fds(media, &em->intf_sfds); |
|
|
|
|
|
|
|
// XXX this should be covered by __update_init_subscribers ? |
|
|
|
@ -2981,18 +3019,20 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca |
|
|
|
__rtcp_mux_set(flags, dst_media); |
|
|
|
__generate_crypto(flags, dst_media, src_media); |
|
|
|
|
|
|
|
unsigned int num_ports = proto_num_ports(sp->num_ports, dst_media, flags, false); |
|
|
|
|
|
|
|
// interface selection |
|
|
|
__init_interface(dst_media, &flags->interface, sp->num_ports); |
|
|
|
__init_interface(dst_media, &flags->interface, num_ports); |
|
|
|
if (dst_media->logical_intf == NULL) |
|
|
|
return -1; // XXX return error code |
|
|
|
|
|
|
|
__ice_offer(flags, dst_media, src_media, ice_is_restart(src_media->ice_agent, sp)); |
|
|
|
|
|
|
|
struct endpoint_map *em = __get_endpoint_map(dst_media, sp->num_ports, NULL, flags, true); |
|
|
|
struct endpoint_map *em = __get_endpoint_map(dst_media, num_ports, NULL, flags, true); |
|
|
|
if (!em) |
|
|
|
return -1; // XXX error - no ports |
|
|
|
|
|
|
|
__num_media_streams(dst_media, sp->num_ports); |
|
|
|
__num_media_streams(dst_media, num_ports); |
|
|
|
__assign_stream_fds(dst_media, &em->intf_sfds); |
|
|
|
|
|
|
|
if (__init_streams(dst_media, NULL, NULL, flags)) |
|
|
|
|