|
|
|
@ -299,11 +299,11 @@ void kernelize(struct packet_stream *stream) {
|
|
|
|
|
struct callmaster *cm = call->callmaster;
|
|
|
|
|
struct packet_stream *sink = NULL;
|
|
|
|
|
|
|
|
|
|
if (stream->kernelized)
|
|
|
|
|
if (PS_ISSET(stream, KERNELIZED))
|
|
|
|
|
return;
|
|
|
|
|
if (cm->conf.kernelfd < 0 || cm->conf.kernelid == -1)
|
|
|
|
|
goto no_kernel;
|
|
|
|
|
if (!stream->rtp)
|
|
|
|
|
if (!PS_ISSET(stream, RTP))
|
|
|
|
|
goto no_kernel;
|
|
|
|
|
if (!stream->sfd)
|
|
|
|
|
goto no_kernel;
|
|
|
|
@ -334,8 +334,8 @@ void kernelize(struct packet_stream *stream) {
|
|
|
|
|
mpt.tos = cm->conf.tos;
|
|
|
|
|
mpt.src_addr.port = sink->sfd->fd.localport;
|
|
|
|
|
mpt.dst_addr.port = sink->endpoint.port;
|
|
|
|
|
mpt.rtcp_mux = stream->media->rtcp_mux;
|
|
|
|
|
mpt.dtls = stream->media->dtls;
|
|
|
|
|
mpt.rtcp_mux = MEDIA_ISSET(stream->media, RTCP_MUX);
|
|
|
|
|
mpt.dtls = MEDIA_ISSET(stream->media, DTLS);
|
|
|
|
|
|
|
|
|
|
if (IN6_IS_ADDR_V4MAPPED(&sink->endpoint.ip46)) {
|
|
|
|
|
mpt.src_addr.family = AF_INET;
|
|
|
|
@ -363,13 +363,13 @@ void kernelize(struct packet_stream *stream) {
|
|
|
|
|
ZERO(stream->kernel_stats);
|
|
|
|
|
|
|
|
|
|
kernel_add_stream(cm->conf.kernelfd, &mpt, 0);
|
|
|
|
|
stream->kernelized = 1;
|
|
|
|
|
PS_SET(stream, KERNELIZED);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
no_kernel:
|
|
|
|
|
stream->kernelized = 1;
|
|
|
|
|
stream->no_kernel_support = 1;
|
|
|
|
|
PS_SET(stream, KERNELIZED);
|
|
|
|
|
PS_SET(stream, NO_KERNEL_SUPPORT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -377,7 +377,7 @@ no_kernel:
|
|
|
|
|
|
|
|
|
|
/* returns: 0 = not a muxed stream, 1 = muxed, RTP, 2 = muxed, RTCP */
|
|
|
|
|
static int rtcp_demux(str *s, struct call_media *media) {
|
|
|
|
|
if (!media->rtcp_mux)
|
|
|
|
|
if (!MEDIA_ISSET(media, RTCP_MUX))
|
|
|
|
|
return 0;
|
|
|
|
|
return rtcp_demux_is_rtcp(s) ? 2 : 1;
|
|
|
|
|
}
|
|
|
|
@ -439,7 +439,7 @@ static void determine_handler(struct packet_stream *in, const struct packet_stre
|
|
|
|
|
const struct streamhandler **sh_pp, *sh;
|
|
|
|
|
const struct streamhandler ***matrix;
|
|
|
|
|
|
|
|
|
|
if (in->has_handler)
|
|
|
|
|
if (PS_ISSET(in, HAS_HANDLER))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!in->media->protocol)
|
|
|
|
@ -448,7 +448,7 @@ static void determine_handler(struct packet_stream *in, const struct packet_stre
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
|
|
matrix = __sh_matrix;
|
|
|
|
|
if (in->media->dtls && out->media->dtls)
|
|
|
|
|
if (MEDIA_ISSET(in->media, DTLS) && MEDIA_ISSET(out->media, DTLS))
|
|
|
|
|
matrix = __sh_matrix_dtls;
|
|
|
|
|
|
|
|
|
|
sh_pp = matrix[in->media->protocol->index];
|
|
|
|
@ -460,7 +460,7 @@ static void determine_handler(struct packet_stream *in, const struct packet_stre
|
|
|
|
|
in->handler = sh;
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
in->has_handler = 1;
|
|
|
|
|
PS_SET(in, HAS_HANDLER);
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
@ -534,13 +534,13 @@ static int stream_packet(struct stream_fd *sfd, str *s, struct sockaddr_in6 *fsi
|
|
|
|
|
if (!stream->sfd)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
if (media->dtls && is_dtls(s)) {
|
|
|
|
|
if (MEDIA_ISSET(media, DTLS) && is_dtls(s)) {
|
|
|
|
|
ret = dtls(stream, s, fsin);
|
|
|
|
|
if (!ret)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stream->stun && is_stun(s)) {
|
|
|
|
|
if (PS_ISSET(stream, STUN) && is_stun(s)) {
|
|
|
|
|
stun_ret = stun(s, stream, fsin);
|
|
|
|
|
if (!stun_ret)
|
|
|
|
|
goto done;
|
|
|
|
@ -554,7 +554,7 @@ static int stream_packet(struct stream_fd *sfd, str *s, struct sockaddr_in6 *fsi
|
|
|
|
|
|
|
|
|
|
in_srtp = stream;
|
|
|
|
|
sink = stream->rtp_sink;
|
|
|
|
|
if (!sink && stream->rtcp) {
|
|
|
|
|
if (!sink && PS_ISSET(stream, RTCP)) {
|
|
|
|
|
sink = stream->rtcp_sink;
|
|
|
|
|
rtcp = 1;
|
|
|
|
|
}
|
|
|
|
@ -612,13 +612,13 @@ static int stream_packet(struct stream_fd *sfd, str *s, struct sockaddr_in6 *fsi
|
|
|
|
|
mutex_lock(&stream->in_lock);
|
|
|
|
|
|
|
|
|
|
use_cand:
|
|
|
|
|
if (!stream->filled)
|
|
|
|
|
if (!PS_ISSET(stream, FILLED))
|
|
|
|
|
goto forward;
|
|
|
|
|
|
|
|
|
|
if (media->asymmetric)
|
|
|
|
|
stream->confirmed = 1;
|
|
|
|
|
if (MEDIA_ISSET(media, ASYMMETRIC))
|
|
|
|
|
PS_SET(stream, CONFIRMED);
|
|
|
|
|
|
|
|
|
|
if (stream->confirmed)
|
|
|
|
|
if (PS_ISSET(stream, CONFIRMED))
|
|
|
|
|
goto kernel_check;
|
|
|
|
|
|
|
|
|
|
if (!call->last_signal || poller_now <= call->last_signal + 3)
|
|
|
|
@ -627,7 +627,7 @@ use_cand:
|
|
|
|
|
ilog(LOG_DEBUG, "Confirmed peer information for port %u - %s",
|
|
|
|
|
sfd->fd.localport, addr);
|
|
|
|
|
|
|
|
|
|
stream->confirmed = 1;
|
|
|
|
|
PS_SET(stream, CONFIRMED);
|
|
|
|
|
update = 1;
|
|
|
|
|
|
|
|
|
|
peerinfo:
|
|
|
|
@ -651,10 +651,10 @@ peerinfo:
|
|
|
|
|
mutex_unlock(&stream->out_lock);
|
|
|
|
|
|
|
|
|
|
kernel_check:
|
|
|
|
|
if (stream->no_kernel_support)
|
|
|
|
|
if (PS_ISSET(stream, NO_KERNEL_SUPPORT))
|
|
|
|
|
goto forward;
|
|
|
|
|
|
|
|
|
|
if (stream->confirmed && sink && sink->confirmed && sink->filled)
|
|
|
|
|
if (PS_ISSET(stream, CONFIRMED) && sink && PS_ISSET(sink, CONFIRMED) && PS_ISSET(sink, FILLED))
|
|
|
|
|
kernelize(stream);
|
|
|
|
|
|
|
|
|
|
forward:
|
|
|
|
@ -820,7 +820,7 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
|
|
|
|
|
if (!sfd || !ps->media)
|
|
|
|
|
goto next;
|
|
|
|
|
|
|
|
|
|
if (ps->media->dtls && sfd->dtls.init && !sfd->dtls.connected)
|
|
|
|
|
if (MEDIA_ISSET(ps->media, DTLS) && sfd->dtls.init && !sfd->dtls.connected)
|
|
|
|
|
dtls(ps, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
if (hlp->ports[sfd->fd.localport])
|
|
|
|
@ -832,7 +832,7 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
|
|
|
|
|
goto next;
|
|
|
|
|
|
|
|
|
|
check = cm->conf.timeout;
|
|
|
|
|
if (!ps->media->recv || !ps->sfd)
|
|
|
|
|
if (!MEDIA_ISSET(ps->media, RECV) || !ps->sfd)
|
|
|
|
|
check = cm->conf.silent_timeout;
|
|
|
|
|
|
|
|
|
|
if (poller_now - ps->last_packet < check)
|
|
|
|
@ -1441,7 +1441,7 @@ static void __fill_stream(struct packet_stream *ps, const struct endpoint *ep, u
|
|
|
|
|
if (memcmp(&ps->advertised_endpoint, &ps->endpoint, sizeof(ps->endpoint)))
|
|
|
|
|
crypto_reset(&ps->crypto);
|
|
|
|
|
ps->advertised_endpoint = ps->endpoint;
|
|
|
|
|
ps->filled = 1;
|
|
|
|
|
PS_SET(ps, FILLED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __init_stream(struct packet_stream *ps) {
|
|
|
|
@ -1450,21 +1450,23 @@ static int __init_stream(struct packet_stream *ps) {
|
|
|
|
|
int active;
|
|
|
|
|
|
|
|
|
|
if (ps->sfd) {
|
|
|
|
|
if (media->sdes)
|
|
|
|
|
if (MEDIA_ISSET(media, SDES))
|
|
|
|
|
crypto_init(&ps->sfd->crypto, &media->sdes_in.params);
|
|
|
|
|
|
|
|
|
|
if (media->dtls && !ps->fallback_rtcp) {
|
|
|
|
|
active = (ps->filled && media->setup_active);
|
|
|
|
|
if (MEDIA_ISSET(media, DTLS) && !PS_ISSET(ps, FALLBACK_RTCP)) {
|
|
|
|
|
active = (PS_ISSET(ps, FILLED) && MEDIA_ISSET(media, SETUP_ACTIVE));
|
|
|
|
|
dtls_connection_init(ps, active, call->dtls_cert);
|
|
|
|
|
|
|
|
|
|
if (!ps->fingerprint_verified && media->fingerprint.hash_func && ps->dtls_cert) {
|
|
|
|
|
if (!PS_ISSET(ps, FINGERPRINT_VERIFIED) && media->fingerprint.hash_func
|
|
|
|
|
&& ps->dtls_cert)
|
|
|
|
|
{
|
|
|
|
|
if (dtls_verify_cert(ps))
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (media->sdes)
|
|
|
|
|
if (MEDIA_ISSET(media, SDES))
|
|
|
|
|
crypto_init(&ps->crypto, &media->sdes_out.params);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
@ -1485,7 +1487,7 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru
|
|
|
|
|
|
|
|
|
|
/* RTP */
|
|
|
|
|
a->rtp_sink = b;
|
|
|
|
|
a->rtp = 1;
|
|
|
|
|
PS_SET(a, RTP);
|
|
|
|
|
|
|
|
|
|
if (sp)
|
|
|
|
|
__fill_stream(a, &sp->rtp_endpoint, port_off);
|
|
|
|
@ -1493,20 +1495,20 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
/* RTCP */
|
|
|
|
|
if (!B->rtcp_mux) {
|
|
|
|
|
if (!MEDIA_ISSET(B, RTCP_MUX)) {
|
|
|
|
|
lb = lb->next;
|
|
|
|
|
assert(lb != NULL);
|
|
|
|
|
b = lb->data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!A->rtcp_mux) {
|
|
|
|
|
if (!MEDIA_ISSET(A, RTCP_MUX)) {
|
|
|
|
|
a->rtcp_sink = NULL;
|
|
|
|
|
a->rtcp = 0;
|
|
|
|
|
PS_CLEAR(a, RTCP);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
a->rtcp_sink = b;
|
|
|
|
|
a->rtcp = 1;
|
|
|
|
|
a->implicit_rtcp = 0;
|
|
|
|
|
PS_SET(a, RTCP);
|
|
|
|
|
PS_CLEAR(a, IMPLICIT_RTCP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ax = a;
|
|
|
|
@ -1519,21 +1521,21 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru
|
|
|
|
|
|
|
|
|
|
a->rtp_sink = NULL;
|
|
|
|
|
a->rtcp_sink = b;
|
|
|
|
|
a->rtp = 0;
|
|
|
|
|
a->rtcp = 1;
|
|
|
|
|
PS_CLEAR(a, RTP);
|
|
|
|
|
PS_SET(a, RTCP);
|
|
|
|
|
a->rtcp_sibling = NULL;
|
|
|
|
|
a->fallback_rtcp = ax->rtcp;
|
|
|
|
|
bf_copy(&a->ps_flags, PS_FLAG_FALLBACK_RTCP, &ax->ps_flags, PS_FLAG_RTCP);
|
|
|
|
|
|
|
|
|
|
ax->rtcp_sibling = a;
|
|
|
|
|
|
|
|
|
|
if (sp) {
|
|
|
|
|
if (!sp->implicit_rtcp) {
|
|
|
|
|
if (!SP_ISSET(sp, IMPLICIT_RTCP)) {
|
|
|
|
|
__fill_stream(a, &sp->rtcp_endpoint, port_off);
|
|
|
|
|
a->implicit_rtcp = 0;
|
|
|
|
|
PS_CLEAR(a, IMPLICIT_RTCP);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
__fill_stream(a, &sp->rtp_endpoint, port_off + 1);
|
|
|
|
|
a->implicit_rtcp = 1;
|
|
|
|
|
PS_SET(a, IMPLICIT_RTCP);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (__init_stream(a))
|
|
|
|
@ -1560,31 +1562,31 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi
|
|
|
|
|
|
|
|
|
|
if (!this->protocol || !this->protocol->srtp) {
|
|
|
|
|
cp->crypto_suite = NULL;
|
|
|
|
|
this->dtls = 0;
|
|
|
|
|
this->sdes = 0;
|
|
|
|
|
this->setup_passive = 0;
|
|
|
|
|
this->setup_active = 0;
|
|
|
|
|
MEDIA_CLEAR(this, DTLS);
|
|
|
|
|
MEDIA_CLEAR(this, SDES);
|
|
|
|
|
MEDIA_CLEAR(this, SETUP_PASSIVE);
|
|
|
|
|
MEDIA_CLEAR(this, SETUP_ACTIVE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flags->opmode == OP_OFFER) {
|
|
|
|
|
/* we use this to remember the peer's preference DTLS vs SDES */
|
|
|
|
|
if (!this->initialized) {
|
|
|
|
|
this->dtls = 1;
|
|
|
|
|
this->sdes = 1;
|
|
|
|
|
if (!MEDIA_ISSET(this, INITIALIZED)) {
|
|
|
|
|
MEDIA_SET(this, DTLS);
|
|
|
|
|
MEDIA_SET(this, SDES);
|
|
|
|
|
}
|
|
|
|
|
/* we always offer actpass */
|
|
|
|
|
this->setup_passive = 1;
|
|
|
|
|
this->setup_active = 1;
|
|
|
|
|
MEDIA_SET(this, SETUP_PASSIVE);
|
|
|
|
|
MEDIA_SET(this, SETUP_ACTIVE);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* if we can be active, we will, otherwise we'll be passive */
|
|
|
|
|
if (this->setup_active)
|
|
|
|
|
this->setup_passive = 0;
|
|
|
|
|
if (MEDIA_ISSET(this, SETUP_ACTIVE))
|
|
|
|
|
MEDIA_CLEAR(this, SETUP_PASSIVE);
|
|
|
|
|
|
|
|
|
|
/* if we're answering and doing DTLS, then skip the SDES stuff */
|
|
|
|
|
if (this->dtls) {
|
|
|
|
|
this->sdes = 0;
|
|
|
|
|
if (MEDIA_ISSET(this, DTLS)) {
|
|
|
|
|
MEDIA_CLEAR(this, SDES);
|
|
|
|
|
goto skip_sdes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1636,8 +1638,8 @@ static void __rtcp_mux_logic(const struct sdp_ng_flags *flags, struct call_media
|
|
|
|
|
if (flags->opmode == OP_ANSWER) {
|
|
|
|
|
/* default is to go with the client's choice, unless we were instructed not
|
|
|
|
|
* to do that in the offer (see below) */
|
|
|
|
|
if (!media->rtcp_mux_override)
|
|
|
|
|
media->rtcp_mux = other_media->rtcp_mux;
|
|
|
|
|
if (!MEDIA_ISSET(media, RTCP_MUX_OVERRIDE))
|
|
|
|
|
bf_copy_same(&media->media_flags, &other_media->media_flags, MEDIA_FLAG_RTCP_MUX);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -1648,27 +1650,27 @@ static void __rtcp_mux_logic(const struct sdp_ng_flags *flags, struct call_media
|
|
|
|
|
|
|
|
|
|
/* default is to pass through the client's choice, unless our peer is already
|
|
|
|
|
* talking rtcp-mux, then we stick to that */
|
|
|
|
|
if (!media->rtcp_mux)
|
|
|
|
|
media->rtcp_mux = other_media->rtcp_mux;
|
|
|
|
|
if (!MEDIA_ISSET(media, RTCP_MUX))
|
|
|
|
|
bf_copy_same(&media->media_flags, &other_media->media_flags, MEDIA_FLAG_RTCP_MUX);
|
|
|
|
|
/* in our offer, we can override the client's choice */
|
|
|
|
|
if (flags->rtcp_mux_offer)
|
|
|
|
|
media->rtcp_mux = 1;
|
|
|
|
|
MEDIA_SET(media, RTCP_MUX);
|
|
|
|
|
else if (flags->rtcp_mux_demux)
|
|
|
|
|
media->rtcp_mux = 0;
|
|
|
|
|
MEDIA_CLEAR(media, RTCP_MUX);
|
|
|
|
|
|
|
|
|
|
/* we can also control what's going to happen in the answer. it
|
|
|
|
|
* depends on what was offered, but by default we go with the other
|
|
|
|
|
* client's choice */
|
|
|
|
|
other_media->rtcp_mux_override = 0;
|
|
|
|
|
if (other_media->rtcp_mux) {
|
|
|
|
|
if (!media->rtcp_mux) {
|
|
|
|
|
MEDIA_CLEAR(other_media, RTCP_MUX_OVERRIDE);
|
|
|
|
|
if (MEDIA_ISSET(other_media, RTCP_MUX)) {
|
|
|
|
|
if (!MEDIA_ISSET(media, RTCP_MUX)) {
|
|
|
|
|
/* rtcp-mux was offered, but we don't offer it ourselves.
|
|
|
|
|
* the answer will not accept rtcp-mux (wasn't offered).
|
|
|
|
|
* the default is to accept the offer, unless we want to
|
|
|
|
|
* explicitly reject it. */
|
|
|
|
|
other_media->rtcp_mux_override = 1;
|
|
|
|
|
MEDIA_SET(other_media, RTCP_MUX_OVERRIDE);
|
|
|
|
|
if (flags->rtcp_mux_reject)
|
|
|
|
|
other_media->rtcp_mux = 0;
|
|
|
|
|
MEDIA_CLEAR(other_media, RTCP_MUX);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* rtcp-mux was offered and we offer it too. default is
|
|
|
|
@ -1676,17 +1678,17 @@ static void __rtcp_mux_logic(const struct sdp_ng_flags *flags, struct call_media
|
|
|
|
|
* either explicitly accept it (possibly demux) or reject
|
|
|
|
|
* it (possible reverse demux). */
|
|
|
|
|
if (flags->rtcp_mux_accept)
|
|
|
|
|
other_media->rtcp_mux_override = 1;
|
|
|
|
|
MEDIA_SET(other_media, RTCP_MUX_OVERRIDE);
|
|
|
|
|
else if (flags->rtcp_mux_reject) {
|
|
|
|
|
other_media->rtcp_mux_override = 1;
|
|
|
|
|
other_media->rtcp_mux = 0;
|
|
|
|
|
MEDIA_SET(other_media, RTCP_MUX_OVERRIDE);
|
|
|
|
|
MEDIA_CLEAR(other_media, RTCP_MUX);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* rtcp-mux was not offered. we may offer it, but since it wasn't
|
|
|
|
|
* offered to us, we must not accept it. */
|
|
|
|
|
other_media->rtcp_mux_override = 1;
|
|
|
|
|
MEDIA_SET(other_media, RTCP_MUX_OVERRIDE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1696,7 +1698,7 @@ static void __unverify_fingerprint(struct call_media *m) {
|
|
|
|
|
|
|
|
|
|
for (l = m->streams.head; l; l = l->next) {
|
|
|
|
|
ps = l->data;
|
|
|
|
|
ps->fingerprint_verified = 0;
|
|
|
|
|
PS_CLEAR(ps, FINGERPRINT_VERIFIED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1745,24 +1747,28 @@ int monologue_offer_answer(struct call_monologue *monologue, GQueue *streams,
|
|
|
|
|
media->protocol = other_media->protocol;
|
|
|
|
|
|
|
|
|
|
/* copy parameters advertised by the sender of this message */
|
|
|
|
|
other_media->rtcp_mux = sp->rtcp_mux;
|
|
|
|
|
bf_copy_same(&other_media->media_flags, &sp->sp_flags,
|
|
|
|
|
SP_FLAG_RTCP_MUX | SP_FLAG_ASYMMETRIC);
|
|
|
|
|
crypto_params_copy(&other_media->sdes_in.params, &sp->crypto);
|
|
|
|
|
other_media->sdes_in.tag = sp->sdes_tag;
|
|
|
|
|
other_media->asymmetric = sp->asymmetric;
|
|
|
|
|
|
|
|
|
|
other_media->recv = media->send = sp->send;
|
|
|
|
|
other_media->send = media->recv = sp->recv;
|
|
|
|
|
bf_copy_same(&media->media_flags, &sp->sp_flags,
|
|
|
|
|
SP_FLAG_SEND | SP_FLAG_RECV);
|
|
|
|
|
bf_copy(&other_media->media_flags, MEDIA_FLAG_RECV, &sp->sp_flags, SP_FLAG_SEND);
|
|
|
|
|
bf_copy(&other_media->media_flags, MEDIA_FLAG_SEND, &sp->sp_flags, SP_FLAG_RECV);
|
|
|
|
|
|
|
|
|
|
other_media->setup_passive = sp->setup_active;
|
|
|
|
|
other_media->setup_active = sp->setup_passive;
|
|
|
|
|
bf_copy(&other_media->media_flags, MEDIA_FLAG_SETUP_PASSIVE,
|
|
|
|
|
&sp->sp_flags, SP_FLAG_SETUP_ACTIVE);
|
|
|
|
|
bf_copy(&other_media->media_flags, MEDIA_FLAG_SETUP_ACTIVE,
|
|
|
|
|
&sp->sp_flags, SP_FLAG_SETUP_PASSIVE);
|
|
|
|
|
if (memcmp(&other_media->fingerprint, &sp->fingerprint, sizeof(sp->fingerprint))) {
|
|
|
|
|
__unverify_fingerprint(other_media);
|
|
|
|
|
other_media->fingerprint = sp->fingerprint;
|
|
|
|
|
}
|
|
|
|
|
other_media->dtls = 0;
|
|
|
|
|
if ((other_media->setup_passive || other_media->setup_active)
|
|
|
|
|
MEDIA_CLEAR(other_media, DTLS);
|
|
|
|
|
if ((MEDIA_ISSET(other_media, SETUP_PASSIVE) || MEDIA_ISSET(other_media, SETUP_ACTIVE))
|
|
|
|
|
&& other_media->fingerprint.hash_func)
|
|
|
|
|
other_media->dtls = 1;
|
|
|
|
|
MEDIA_SET(other_media, DTLS);
|
|
|
|
|
|
|
|
|
|
/* control rtcp-mux */
|
|
|
|
|
__rtcp_mux_logic(flags, media, other_media);
|
|
|
|
@ -1784,7 +1790,7 @@ int monologue_offer_answer(struct call_monologue *monologue, GQueue *streams,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* mark initial offer/answer as done */
|
|
|
|
|
media->initialized = 1;
|
|
|
|
|
MEDIA_SET(media, INITIALIZED);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* determine number of consecutive ports needed locally.
|
|
|
|
@ -1837,14 +1843,14 @@ error:
|
|
|
|
|
|
|
|
|
|
/* must be called with in_lock held or call->master_lock held in W */
|
|
|
|
|
static void unkernelize(struct packet_stream *p) {
|
|
|
|
|
if (!p->kernelized)
|
|
|
|
|
if (!PS_ISSET(p, KERNELIZED))
|
|
|
|
|
return;
|
|
|
|
|
if (p->no_kernel_support)
|
|
|
|
|
if (PS_ISSET(p, NO_KERNEL_SUPPORT))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
kernel_del_stream(p->call->callmaster->conf.kernelfd, p->sfd->fd.localport);
|
|
|
|
|
|
|
|
|
|
p->kernelized = 0;
|
|
|
|
|
PS_CLEAR(p, KERNELIZED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* called lock-free, but must hold a reference to the call */
|
|
|
|
@ -1892,7 +1898,7 @@ static void call_destroy(struct call *c) {
|
|
|
|
|
for (o = md->streams.head; o; o = o->next) {
|
|
|
|
|
ps = o->data;
|
|
|
|
|
|
|
|
|
|
if (ps->fallback_rtcp)
|
|
|
|
|
if (PS_ISSET(ps, FALLBACK_RTCP))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
smart_ntop_p(buf, &ps->endpoint.ip46, sizeof(buf));
|
|
|
|
@ -1901,7 +1907,7 @@ static void call_destroy(struct call *c) {
|
|
|
|
|
md->index,
|
|
|
|
|
(unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0),
|
|
|
|
|
buf, ps->endpoint.port,
|
|
|
|
|
(!ps->rtp && ps->rtcp) ? " (RTCP)" : "",
|
|
|
|
|
(!PS_ISSET(ps, RTP) && PS_ISSET(ps, RTCP)) ? " (RTCP)" : "",
|
|
|
|
|
ps->stats.packets,
|
|
|
|
|
ps->stats.bytes,
|
|
|
|
|
ps->stats.errors);
|
|
|
|
@ -2184,8 +2190,8 @@ static void __monologue_tag(struct call_monologue *ml, const str *tag) {
|
|
|
|
|
|
|
|
|
|
static void __stream_unkernelize(struct packet_stream *ps) {
|
|
|
|
|
unkernelize(ps);
|
|
|
|
|
ps->confirmed = 0;
|
|
|
|
|
ps->has_handler = 0;
|
|
|
|
|
PS_CLEAR(ps, CONFIRMED);
|
|
|
|
|
PS_CLEAR(ps, HAS_HANDLER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* must be called with call->master_lock held in W */
|
|
|
|
|